mirror of
https://github.com/aristocratos/btop.git
synced 2024-09-29 08:41:19 +13:00
Change Proc::collect to return a reference to Proc::current_procs instead of a new vector
This commit is contained in:
parent
deec8f20e0
commit
9667fe65b4
4 changed files with 31 additions and 38 deletions
6
btop.cpp
6
btop.cpp
|
@ -332,12 +332,6 @@ int main(int argc, char **argv){
|
||||||
exit(0);
|
exit(0);
|
||||||
}
|
}
|
||||||
|
|
||||||
if (false) {
|
|
||||||
string a = "⣿ ⣿\n⣿⣿⣿⣿ ⣿\n⣿⣿⣿⣿ ⣿\n⣿⣿⣿⣿ ⣿\n⣿⣿⣿";
|
|
||||||
cout << a << endl;
|
|
||||||
exit(0);
|
|
||||||
}
|
|
||||||
|
|
||||||
if (false) {
|
if (false) {
|
||||||
|
|
||||||
vector<long long> mydata;
|
vector<long long> mydata;
|
||||||
|
|
|
@ -126,19 +126,19 @@ namespace Config {
|
||||||
|
|
||||||
//* Set config value <name> to bool <value>
|
//* Set config value <name> to bool <value>
|
||||||
void set(string name, bool value){
|
void set(string name, bool value){
|
||||||
if (_locked()) boolsTmp[name] = value;
|
if (_locked()) boolsTmp.insert_or_assign(name, value);
|
||||||
else bools.at(name) = value;
|
else bools.at(name) = value;
|
||||||
}
|
}
|
||||||
|
|
||||||
//* Set config value <name> to int <value>
|
//* Set config value <name> to int <value>
|
||||||
void set(string name, int value){
|
void set(string name, int value){
|
||||||
if (_locked()) intsTmp[name] = value;
|
if (_locked()) intsTmp.insert_or_assign(name, value);
|
||||||
ints.at(name) = value;
|
ints.at(name) = value;
|
||||||
}
|
}
|
||||||
|
|
||||||
//* Set config value <name> to string <value>
|
//* Set config value <name> to string <value>
|
||||||
void set(string name, string value){
|
void set(string name, string value){
|
||||||
if (_locked()) stringsTmp[name] = value;
|
if (_locked()) stringsTmp.insert_or_assign(name, value);
|
||||||
else strings.at(name) = value;
|
else strings.at(name) = value;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -146,36 +146,36 @@ namespace Config {
|
||||||
void flip(string name){
|
void flip(string name){
|
||||||
if (_locked()) {
|
if (_locked()) {
|
||||||
if (boolsTmp.contains(name)) boolsTmp.at(name) = !boolsTmp.at(name);
|
if (boolsTmp.contains(name)) boolsTmp.at(name) = !boolsTmp.at(name);
|
||||||
else boolsTmp[name] = !bools.at(name);
|
else boolsTmp.insert_or_assign(name, (!bools.at(name)));
|
||||||
}
|
}
|
||||||
else bools.at(name) = !bools.at(name);
|
else bools.at(name) = !bools.at(name);
|
||||||
}
|
}
|
||||||
|
|
||||||
//* Wait if locked then lock config and cache changes until unlock
|
//* Wait if locked then lock config and cache changes until unlock
|
||||||
void lock(){
|
void lock(){
|
||||||
atomic_wait_set(locked, true);
|
atomic_wait_set(locked);
|
||||||
}
|
}
|
||||||
|
|
||||||
//* Unlock config and write any cached values to config
|
//* Unlock config and write any cached values to config
|
||||||
void unlock(){
|
void unlock(){
|
||||||
atomic_wait_set(writelock, true);
|
atomic_wait_set(writelock);
|
||||||
if (stringsTmp.size() > 0) {
|
if (stringsTmp.size() > 0) {
|
||||||
for (auto& item : stringsTmp){
|
for (auto& item : stringsTmp){
|
||||||
strings.at(item.first) = item.second;
|
strings.at(item.first) = item.second;
|
||||||
}
|
}
|
||||||
stringsTmp.clear(); stringsTmp.compact();
|
stringsTmp.clear();
|
||||||
}
|
}
|
||||||
if (intsTmp.size() > 0) {
|
if (intsTmp.size() > 0) {
|
||||||
for (auto& item : intsTmp){
|
for (auto& item : intsTmp){
|
||||||
ints.at(item.first) = item.second;
|
ints.at(item.first) = item.second;
|
||||||
}
|
}
|
||||||
intsTmp.clear(); intsTmp.compact();
|
intsTmp.clear();
|
||||||
}
|
}
|
||||||
if (boolsTmp.size() > 0) {
|
if (boolsTmp.size() > 0) {
|
||||||
for (auto& item : boolsTmp){
|
for (auto& item : boolsTmp){
|
||||||
bools.at(item.first) = item.second;
|
bools.at(item.first) = item.second;
|
||||||
}
|
}
|
||||||
boolsTmp.clear(); boolsTmp.compact();
|
boolsTmp.clear();
|
||||||
}
|
}
|
||||||
writelock.store(false);
|
writelock.store(false);
|
||||||
locked.store(false);
|
locked.store(false);
|
||||||
|
|
|
@ -60,7 +60,6 @@ namespace Tools {
|
||||||
|
|
||||||
namespace Proc {
|
namespace Proc {
|
||||||
namespace {
|
namespace {
|
||||||
uint64_t tstamp;
|
|
||||||
struct p_cache {
|
struct p_cache {
|
||||||
string name, cmd, user;
|
string name, cmd, user;
|
||||||
uint64_t cpu_t = 0, cpu_s = 0;
|
uint64_t cpu_t = 0, cpu_s = 0;
|
||||||
|
@ -79,7 +78,8 @@ namespace Proc {
|
||||||
uint64_t old_cputimes = 0;
|
uint64_t old_cputimes = 0;
|
||||||
size_t numpids = 500;
|
size_t numpids = 500;
|
||||||
atomic<bool> stop (false);
|
atomic<bool> stop (false);
|
||||||
atomic<bool> running (false);
|
atomic<bool> collecting (false);
|
||||||
|
atomic<bool> drawing (false);
|
||||||
array<string, 8> sort_array = {
|
array<string, 8> sort_array = {
|
||||||
"pid",
|
"pid",
|
||||||
"name",
|
"name",
|
||||||
|
@ -90,7 +90,7 @@ namespace Proc {
|
||||||
"cpu direct",
|
"cpu direct",
|
||||||
"cpu lazy",
|
"cpu lazy",
|
||||||
};
|
};
|
||||||
unordered_flat_map<string, uint> sort_map;
|
unordered_flat_map<string, int> sort_map;
|
||||||
|
|
||||||
//* proc_info: pid, name, cmd, threads, user, mem, cpu_p, cpu_c, state, cpu_n, p_nice, ppid
|
//* proc_info: pid, name, cmd, threads, user, mem, cpu_p, cpu_c, state, cpu_n, p_nice, ppid
|
||||||
struct proc_info {
|
struct proc_info {
|
||||||
|
@ -105,16 +105,17 @@ namespace Proc {
|
||||||
uint ppid = 0;
|
uint ppid = 0;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
vector<proc_info> current_procs;
|
||||||
|
|
||||||
//* Collects process information from /proc and returns a vector of proc_info structs
|
|
||||||
auto collect(string sorting="pid", bool reverse=false, string filter="", bool per_core=true){
|
//* Collects process information from /proc, saves to and returns reference to Proc::current_procs;
|
||||||
running.store(true);
|
auto& collect(string sorting="pid", bool reverse=false, string filter="", bool per_core=true){
|
||||||
|
atomic_wait_set(collecting);
|
||||||
ifstream pread;
|
ifstream pread;
|
||||||
auto uptime = system_uptime();
|
auto uptime = system_uptime();
|
||||||
auto sortint = (sort_map.contains(sorting)) ? sort_map[sorting] : 7;
|
|
||||||
vector<proc_info> procs;
|
vector<proc_info> procs;
|
||||||
procs.reserve((numpids + 10));
|
procs.reserve((numpids + 10));
|
||||||
numpids = 0;
|
int npids = 0;
|
||||||
int cmult = (per_core) ? Global::coreCount : 1;
|
int cmult = (per_core) ? Global::coreCount : 1;
|
||||||
|
|
||||||
//* Update uid_user map if /etc/passwd changed since last run
|
//* Update uid_user map if /etc/passwd changed since last run
|
||||||
|
@ -143,22 +144,21 @@ namespace Proc {
|
||||||
for (uint64_t times; pread >> times; cputimes += times);
|
for (uint64_t times; pread >> times; cputimes += times);
|
||||||
pread.close();
|
pread.close();
|
||||||
}
|
}
|
||||||
else return procs;
|
else return current_procs;
|
||||||
|
|
||||||
//* Iterate over all pids in /proc
|
//* Iterate over all pids in /proc
|
||||||
for (auto& d: fs::directory_iterator(proc_path)){
|
for (auto& d: fs::directory_iterator(proc_path)){
|
||||||
if (pread.is_open()) pread.close();
|
if (pread.is_open()) pread.close();
|
||||||
if (stop.load()) {
|
if (stop.load()) {
|
||||||
procs.clear();
|
collecting.store(false);
|
||||||
running.store(false);
|
|
||||||
stop.store(false);
|
stop.store(false);
|
||||||
return procs;
|
return current_procs;
|
||||||
}
|
}
|
||||||
|
|
||||||
string pid_str = d.path().filename();
|
string pid_str = d.path().filename();
|
||||||
bool new_cache = false;
|
bool new_cache = false;
|
||||||
if (d.is_directory() && isdigit(pid_str[0])) {
|
if (d.is_directory() && isdigit(pid_str[0])) {
|
||||||
numpids++;
|
npids++;
|
||||||
proc_info new_proc (stoul(pid_str));
|
proc_info new_proc (stoul(pid_str));
|
||||||
|
|
||||||
//* Cache program name, command and username
|
//* Cache program name, command and username
|
||||||
|
@ -298,7 +298,7 @@ namespace Proc {
|
||||||
|
|
||||||
|
|
||||||
//* Sort processes vector
|
//* Sort processes vector
|
||||||
std::ranges::sort(procs, [&sortint, &reverse](proc_info& a, proc_info& b) {
|
std::ranges::sort(procs, [sortint = sort_map.at(sorting), &reverse](proc_info& a, proc_info& b) {
|
||||||
switch (sortint) {
|
switch (sortint) {
|
||||||
case 0: return (reverse) ? a.pid < b.pid : a.pid > b.pid;
|
case 0: return (reverse) ? a.pid < b.pid : a.pid > b.pid;
|
||||||
case 1: return (reverse) ? a.name < b.name : a.name > b.name;
|
case 1: return (reverse) ? a.name < b.name : a.name > b.name;
|
||||||
|
@ -314,7 +314,7 @@ namespace Proc {
|
||||||
);
|
);
|
||||||
|
|
||||||
//* When using "cpu lazy" sorting push processes with high cpu usage to the front regardless of cumulative usage
|
//* When using "cpu lazy" sorting push processes with high cpu usage to the front regardless of cumulative usage
|
||||||
if (sortint == 7 && !reverse) {
|
if (sort_map.at(sorting) == 7 && !reverse) {
|
||||||
double max = 10.0, target = 30.0;
|
double max = 10.0, target = 30.0;
|
||||||
for (size_t i = 0, offset = 0; i < procs.size(); i++) {
|
for (size_t i = 0, offset = 0; i < procs.size(); i++) {
|
||||||
if (i <= 5 && procs[i].cpu_p > max) max = procs[i].cpu_p;
|
if (i <= 5 && procs[i].cpu_p > max) max = procs[i].cpu_p;
|
||||||
|
@ -325,11 +325,10 @@ namespace Proc {
|
||||||
}
|
}
|
||||||
|
|
||||||
//* Clear dead processes from cache at a regular interval
|
//* Clear dead processes from cache at a regular interval
|
||||||
if (++counter >= 10000 || (filter.empty() && cache.size() > procs.size() + 100)) {
|
if (++counter >= 10000 || ((int)cache.size() > npids + 100)) {
|
||||||
unordered_flat_map<uint, p_cache> r_cache;
|
unordered_flat_map<uint, p_cache> r_cache;
|
||||||
r_cache.reserve(procs.size());
|
r_cache.reserve(procs.size());
|
||||||
counter = 0;
|
counter = 0;
|
||||||
Logger::debug("Cleared proc cache");
|
|
||||||
if (filter.empty()) {
|
if (filter.empty()) {
|
||||||
for (auto& p : procs) r_cache[p.pid] = cache[p.pid];
|
for (auto& p : procs) r_cache[p.pid] = cache[p.pid];
|
||||||
cache.swap(r_cache);
|
cache.swap(r_cache);
|
||||||
|
@ -337,15 +336,15 @@ namespace Proc {
|
||||||
else cache.clear();
|
else cache.clear();
|
||||||
}
|
}
|
||||||
old_cputimes = cputimes;
|
old_cputimes = cputimes;
|
||||||
tstamp = time_ms();
|
atomic_wait(drawing);
|
||||||
running.store(false);
|
current_procs.swap(procs);
|
||||||
return procs;
|
numpids = npids;
|
||||||
|
collecting.store(false);
|
||||||
|
return current_procs;
|
||||||
}
|
}
|
||||||
|
|
||||||
//* Initialize needed variables for collect
|
//* Initialize needed variables for collect
|
||||||
void init(){
|
void init(){
|
||||||
tstamp = time_ms();
|
|
||||||
|
|
||||||
proc_path = (fs::is_directory(fs::path("/proc")) && access("/proc", R_OK) != -1) ? "/proc" : "";
|
proc_path = (fs::is_directory(fs::path("/proc")) && access("/proc", R_OK) != -1) ? "/proc" : "";
|
||||||
if (proc_path.empty()) {
|
if (proc_path.empty()) {
|
||||||
string errmsg = "Proc filesystem not found or no permission to read from it!";
|
string errmsg = "Proc filesystem not found or no permission to read from it!";
|
||||||
|
|
|
@ -441,7 +441,7 @@ namespace Tools {
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
//* Waits for <atom> to not be <val> and then sets it to <val> again
|
//* Waits for <atom> to not be <val> and then sets it to <val> again
|
||||||
void atomic_wait_set(atomic<bool>& atom, bool val){
|
void atomic_wait_set(atomic<bool>& atom, bool val=true){
|
||||||
atomic_wait(atom, val);
|
atomic_wait(atom, val);
|
||||||
atom.store(val);
|
atom.store(val);
|
||||||
}
|
}
|
||||||
|
|
Loading…
Reference in a new issue