summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authoraristocratos <gnmjpl@gmail.com>2021-05-15 13:24:24 +0200
committeraristocratos <gnmjpl@gmail.com>2021-05-15 13:24:24 +0200
commit8364d856c86f0ff25589e864507b3efe9633a2fb (patch)
tree69b18549bee9fdcb364ae01408cdfc28492e0939
parentc00728231739a5a07d1e28e84f6123246ea365ee (diff)
changed proc cache to be more effective
-rw-r--r--README.md4
-rw-r--r--btop.cpp19
-rw-r--r--src/btop_config.h2
-rw-r--r--src/btop_globs.h2
-rw-r--r--src/btop_input.h2
-rw-r--r--src/btop_linux.h154
-rw-r--r--src/btop_theme.h2
-rw-r--r--src/btop_tools.h15
8 files changed, 106 insertions, 94 deletions
diff --git a/README.md b/README.md
index eaa1aca..aa81b46 100644
--- a/README.md
+++ b/README.md
@@ -112,7 +112,7 @@ Look to the creators of the terminal emulator you use to fix these issues if the
None
-But will need G++ 10 or Clang 11 if compiling from source.
+But will need G++ 10 if compiling from source.
## Screenshots
@@ -165,7 +165,7 @@ Config files stored in "$HOME/.config/btop" folder
#### btop.cfg: (auto generated if not found)
-"/etc/bpytop.conf" will be used as default seed for config file creation if it exists. ("/usr/local/etc/bpytop.conf" on BSD)
+"/etc/btop.conf" will be used as default seed for config file creation if it exists. ("/usr/local/etc/btop.conf" on BSD)
```bash
#? Config file for btop v. 0.0.1
diff --git a/btop.cpp b/btop.cpp
index 84650dc..522b1d9 100644
--- a/btop.cpp
+++ b/btop.cpp
@@ -16,18 +16,12 @@ indent = tab
tab-size = 4
*/
-#include <iostream>
+
#include <string>
-#include <cmath>
#include <vector>
-#include <map>
-#include <tuple>
#include <thread>
#include <future>
#include <atomic>
-#include <filesystem>
-
-#include <unistd.h>
#include <btop_globs.h>
#include <btop_tools.h>
@@ -149,7 +143,7 @@ int main(int argc, char **argv){
if (argc > 1) argumentParser(argc, argv);
//? Init for Linux
- if (Global::SYSTEM == "linux") {
+ if (Global::System == "linux") {
Global::proc_path = (fs::is_directory(fs::path("/proc"))) ? fs::path("/proc") : Global::proc_path;
if (Global::proc_path.empty()) {
cout << "ERROR: Proc filesystem not detected!" << endl;
@@ -293,11 +287,10 @@ int main(int argc, char **argv){
cout << Mv::restore << Mv::u(2) << Mv::r(20) << rjustify("Filter: " + filter + filter_cur + string(Term::width / 3, ' ') +
"Sorting: " + Proc::sort_vector[sortint], Term::width - 22, true, filtering) << Mv::restore << flush;
- for (auto& [lpid, lname, lcmd, lthread, luser, lmem, lcpu, lcpu_s] : plist){
- (void) lcpu_s;
- ostring += rjustify(to_string(lpid), 8) + " " + ljustify(lname, 16) + " " + ljustify(lcmd, Term::width - 66, true) + " " +
- rjustify(to_string(lthread), 5) + " " + ljustify(luser, 10) + " " + rjustify(floating_humanizer(lmem, true), 5) + string(11, ' ');
- ostring += (lcpu > 100) ? rjustify(to_string(lcpu), 3) + " " : rjustify(to_string(lcpu), 4);
+ for (Proc::proc_info& procs : plist){
+ ostring += rjustify(to_string(procs.pid), 8) + " " + ljustify(procs.name, 16) + " " + ljustify(procs.cmd, Term::width - 66, true) + " " +
+ rjustify(to_string(procs.threads), 5) + " " + ljustify(procs.user, 10) + " " + rjustify(floating_humanizer(procs.mem, true), 5) + string(11, ' ');
+ ostring += (procs.cpu_p > 100) ? rjustify(to_string(procs.cpu_p), 3) + " " : rjustify(to_string(procs.cpu_p), 4);
ostring += "\n";
if (lc++ > Term::height - 20) break;
}
diff --git a/src/btop_config.h b/src/btop_config.h
index 5a0e813..60f8a42 100644
--- a/src/btop_config.h
+++ b/src/btop_config.h
@@ -17,7 +17,7 @@ tab-size = 4
*/
#ifndef _btop_config_included_
-#define _btop_config_included_
+#define _btop_config_included_ 1
#include <string>
#include <vector>
diff --git a/src/btop_globs.h b/src/btop_globs.h
index f5011f1..0fba894 100644
--- a/src/btop_globs.h
+++ b/src/btop_globs.h
@@ -17,7 +17,7 @@ tab-size = 4
*/
#ifndef _btop_globs_included_
-#define _btop_globs_included_
+#define _btop_globs_included_ 1
#include <string>
#include <map>
diff --git a/src/btop_input.h b/src/btop_input.h
index 3e16168..5f1cc29 100644
--- a/src/btop_input.h
+++ b/src/btop_input.h
@@ -17,7 +17,7 @@ tab-size = 4
*/
#ifndef _btop_input_included_
-#define _btop_input_included_
+#define _btop_input_included_ 1
#include <string>
#include <map>
diff --git a/src/btop_linux.h b/src/btop_linux.h
index f040d9d..8d5ca33 100644
--- a/src/btop_linux.h
+++ b/src/btop_linux.h
@@ -17,7 +17,7 @@ tab-size = 4
*/
#ifndef _btop_linux_included_
-#define _btop_linux_included_
+#define _btop_linux_included_ 1
#include <string>
#include <vector>
@@ -39,29 +39,42 @@ using namespace std;
namespace Global {
- const string SYSTEM = "linux";
+ const string System = "linux";
filesystem::path proc_path;
}
+//? --------------------------------------------------- FUNCTIONS -----------------------------------------------------
+
+double system_uptime(){
+ string upstr;
+ ifstream pread("/proc/uptime");
+ getline(pread, upstr, ' ');
+ pread.close();
+ return stod(upstr);
+}
+
+//? ------------------------------------------------- NAMESPACES ------------------------------------------------------
+
namespace Proc {
namespace {
uint64_t tstamp;
long int clk_tck;
- struct p_cache { string name, cmd, user; };
- map<int, p_cache> cache;
+ struct p_cache {
+ string name, cmd, user;
+ uint64_t cpu_t = 0, cpu_s = 0;
+ };
+ map<uint, p_cache> cache;
map<string, string> uid_user;
fs::path passwd_path;
fs::file_time_type passwd_time;
- map<int, uint64_t> cpu_times;
- map<int, uint64_t> cpu_second;
uint counter = 0;
long page_size = sysconf(_SC_PAGE_SIZE);
}
- atomic<bool> stop;
- atomic<bool> running;
+ atomic<bool> stop (false);
+ atomic<bool> running (false);
vector<string> sort_vector = {
"pid",
"name",
@@ -76,7 +89,7 @@ namespace Proc {
//* proc_info: pid, name, cmd, threads, user, mem, cpu_p, cpu_c
struct proc_info {
- int pid;
+ uint pid;
string name, cmd;
size_t threads;
string user;
@@ -88,18 +101,20 @@ namespace Proc {
//* Collects process information from /proc and returns a vector of proc_info structs
auto collect(string sorting="pid", bool reverse=false, string filter=""){
running.store(true);
- int pid;
+ uint pid;
uint64_t cpu_t, rss_mem;
double cpu, cpu_s;
+ bool new_cache;
size_t threads;
ifstream pread;
- string pid_str, name, cmd, attr, user, instr, uid, status, tmpstr, smap;
+ string pid_str, name, cmd, attr, user, instr, uid, status, tmpstr;
auto since_last = time_ms() - tstamp;
if (since_last < 1) since_last = 1;
auto uptime = system_uptime();
auto sortint = (sort_map.contains(sorting)) ? sort_map[sorting] : 7;
vector<string> pstat;
vector<proc_info> procs;
+ vector<uint> c_pids;
//* Update uid_user map if /etc/passwd changed since last run
if (!passwd_path.empty() && fs::last_write_time(passwd_path) != passwd_time) {
@@ -121,7 +136,7 @@ namespace Proc {
}
- //* Iterate over all pid directories in /proc and get relevant values
+ //* Iterate over all pids in /proc and get relevant values
for (auto& d: fs::directory_iterator(Global::proc_path)){
if (stop.load()) {
procs.clear();
@@ -132,50 +147,15 @@ namespace Proc {
pid_str = fs::path(d.path()).filename();
cpu = 0.0;
rss_mem = 0;
+ new_cache = false;
if (d.is_directory() && isdigit(pid_str[0])) {
- pid = stoi(pid_str);
-
- //* Get cpu usage, cpu cumulative and threads from /proc/[pid]/stat
- if (fs::exists((string)d.path() + "/stat")) {
- pread.clear(); pstat.clear();
- ifstream pread((string)d.path() + "/stat");
- if (pread.good()) while (getline(pread, instr, ' ')) pstat.push_back(instr);
- pread.close();
-
- if (pstat.size() < 37) continue;
-
- //? Process number of threads
- threads = stoul(pstat[19]);
-
- //? Process utime + stime
- cpu_t = stoull(pstat[13]) + stoull(pstat[14]);
- if (!cpu_times.contains(pid)) cpu_times[pid] = cpu_t;
-
- //? Cache process start time
- if (!cpu_second.contains(pid)) cpu_second[pid] = stoull(pstat[21]);
-
- //? Process cpu usage since last update, 100'000 because (100 percent * 1000 milliseconds) for correct conversion
- cpu = static_cast<double>(100000 * (cpu_t - cpu_times[pid]) / since_last) / clk_tck;
-
- //? Process cumulative cpu usage since process start
- cpu_s = static_cast<double>((cpu_t / clk_tck) / (uptime - (cpu_second[pid] / clk_tck)));
- cpu_times[pid] = cpu_t;
- }
-
- //* Get RSS memory in bytes from /proc/[pid]/statm
- if (fs::exists((string)d.path() + "/statm")) {
- pread.clear(); tmpstr.clear();
- ifstream pread((string)d.path() + "/statm");
- if (pread.good()) {
- pread.ignore(numeric_limits<streamsize>::max(), ' ');
- pread >> rss_mem;
- rss_mem *= page_size;
- }
- pread.close();
- }
+ pid = stoul(pid_str);
+ c_pids.push_back(pid);
//* Cache program name, command and username
if (!cache.contains(pid)) {
+ name.clear(); cmd.clear(); user.clear();
+ new_cache = true;
if (fs::exists((string)d.path() + "/comm")) {
pread.clear(); name.clear();
ifstream pread((string)d.path() + "/comm");
@@ -210,6 +190,54 @@ namespace Proc {
cache[pid] = p_cache(name, cmd, user);
}
+ //* Get cpu usage, cpu cumulative and threads from /proc/[pid]/stat
+ if (fs::exists((string)d.path() + "/stat")) {
+ pread.clear(); pstat.clear();
+ ifstream pread((string)d.path() + "/stat");
+ if (pread.good()) while (getline(pread, instr, ' ')) pstat.push_back(instr);
+ pread.close();
+
+ if (pstat.size() < 37) continue;
+
+ //? Process number of threads
+ threads = stoul(pstat[19]);
+
+ //? Process utime + stime
+ cpu_t = stoull(pstat[13]) + stoull(pstat[14]);
+
+ //? Cache cpu times and cpu seconds
+ if (new_cache) {
+ cache[pid].cpu_t = cpu_t;
+ cache[pid].cpu_s = stoull(pstat[21]);
+ }
+
+ //? Cache process start time
+ // if (!cpu_second.contains(pid)) cpu_second[pid] = stoull(pstat[21]);
+
+ //? Process cpu usage since last update, 100'000 because (100 percent * 1000 milliseconds) for correct conversion
+ cpu = static_cast<double>(100000 * (cpu_t - cache[pid].cpu_t) / since_last) / clk_tck;
+
+ //? Process cumulative cpu usage since process start
+ cpu_s = static_cast<double>((cpu_t / clk_tck) / (uptime - (cache[pid].cpu_s / clk_tck)));
+
+ //? Add latest cpu times to cache
+ cache[pid].cpu_t = cpu_t;
+ }
+
+ //* Get RSS memory in bytes from /proc/[pid]/statm
+ if (fs::exists((string)d.path() + "/statm")) {
+ pread.clear(); tmpstr.clear();
+ ifstream pread((string)d.path() + "/statm");
+ if (pread.good()) {
+ pread.ignore(numeric_limits<streamsize>::max(), ' ');
+ pread >> rss_mem;
+ rss_mem *= page_size;
+ }
+ pread.close();
+ }
+
+
+
// //* Match filter if applicable
if (!filter.empty() &&
pid_str.find(filter) == string::npos && //? Pid
@@ -218,7 +246,7 @@ namespace Proc {
cache[pid].user.find(filter) == string::npos //? User
) continue;
- //* Create tuple
+ //* Create proc_info
procs.push_back(proc_info(pid, cache[pid].name, cache[pid].cmd, threads, cache[pid].user, rss_mem, cpu, cpu_s));
}
}
@@ -235,15 +263,15 @@ namespace Proc {
case 3: return (reverse) ? a.threads < b.threads : a.threads > b.threads;
case 4: return (reverse) ? a.user < b.user : a.user > b.user;
case 5: return (reverse) ? a.mem < b.mem : a.mem > b.mem;
- case 6: return (reverse) ? a.pid < b.pid : a.pid > b.pid;
- case 7: return (reverse) ? a.pid < b.pid : a.pid > b.pid;
+ case 6: return (reverse) ? a.cpu_p < b.cpu_p : a.cpu_p > b.cpu_p;
+ case 7: return (reverse) ? a.cpu_c < b.cpu_c : a.cpu_c > b.cpu_c;
}
return false;
}
);
//* When using "cpu lazy" sorting push processes with high cpu usage to the front regardless of cumulative usage
- if (sortint == 6 && !reverse) {
+ if (sortint == 7 && !reverse) {
double max = 10.0, target = 30.0;
for (size_t i = 0, offset = 0; i < procs.size(); i++) {
if (i <= 5 && procs[i].cpu_p > max) max = procs[i].cpu_p;
@@ -254,11 +282,14 @@ namespace Proc {
}
//* Clear all cached values at a regular interval to get rid of dead processes
- if (++counter >= 10000 || (filter.empty() && cache.size() > procs.size() + 100)) {
+ if (++counter >= 5 || (filter.empty() && cache.size() > procs.size() + 100)) {
+ map<uint, p_cache> r_cache;
counter = 0;
- cache.clear();
- cpu_times.clear();
- cpu_second.clear();
+ for (auto& p : c_pids){
+ r_cache[p] = cache[p];
+ }
+ cache = move(r_cache);
+
}
tstamp = time_ms();
@@ -266,14 +297,13 @@ namespace Proc {
return procs;
}
+ //* Initialize needed variables for collect
void init(){
clk_tck = sysconf(_SC_CLK_TCK);
tstamp = time_ms();
- stop.store(false);
passwd_path = (fs::exists(fs::path("/etc/passwd"))) ? fs::path("/etc/passwd") : passwd_path;
uint i = 0;
for (auto& item : sort_vector) sort_map[item] = i++;
- // collect();
}
};
diff --git a/src/btop_theme.h b/src/btop_theme.h
index ae75c5c..64126fe 100644
--- a/src/btop_theme.h
+++ b/src/btop_theme.h
@@ -17,7 +17,7 @@ tab-size = 4
*/
#ifndef _btop_theme_included_
-#define _btop_theme_included_
+#define _btop_theme_included_ 1
#include <string>
#include <cmath>
diff --git a/src/btop_tools.h b/src/btop_tools.h
index f1c99c6..3367f25 100644
--- a/src/btop_tools.h
+++ b/src/btop_tools.h
@@ -17,16 +17,13 @@ tab-size = 4
*/
#ifndef _btop_tools_included_
-#define _btop_tools_included_
+#define _btop_tools_included_ 1
#include <string>
#include <cmath>
#include <vector>
-#include <map>
+#include <iostream>
#include <chrono>
-#include <thread>
-#include <algorithm>
-#include <fstream>
#include <regex>
#include <unistd.h>
@@ -346,14 +343,6 @@ string sec_to_dhms(uint sec){
return out;
}
-double system_uptime(){
- string upstr;
- ifstream pread("/proc/uptime");
- getline(pread, upstr, ' ');
- pread.close();
- return stod(upstr);
-}
-
//* Scales up in steps of 1024 to highest possible unit and returns string with unit suffixed
//* bit=True or defaults to bytes
//* start=int to set 1024 multiplier starting unit