Change Proc::collect to return a reference to Proc::current_procs instead of a new vector

This commit is contained in:
aristocratos 2021-06-06 22:49:24 +02:00
parent deec8f20e0
commit 9667fe65b4
4 changed files with 31 additions and 38 deletions

View file

@ -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;

View file

@ -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);

View file

@ -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!";

View file

@ -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);
} }