mirror of https://github.com/aristocratos/btop.git
proc/[pid]/stat collection improvement
This commit is contained in:
parent
36f0264485
commit
db3bf06485
|
@ -128,20 +128,18 @@ namespace Proc {
|
||||||
|
|
||||||
int children = 0;
|
int children = 0;
|
||||||
for (auto& p : rng::equal_range(in_procs, cur_proc.pid, rng::less{}, &proc_info::ppid)) {
|
for (auto& p : rng::equal_range(in_procs, cur_proc.pid, rng::less{}, &proc_info::ppid)) {
|
||||||
children++;
|
|
||||||
if (collapsed) {
|
if (collapsed) {
|
||||||
out_procs.back().cpu_p += p.cpu_p;
|
out_procs.back().cpu_p += p.cpu_p;
|
||||||
out_procs.back().mem += p.mem;
|
out_procs.back().mem += p.mem;
|
||||||
out_procs.back().threads += p.threads;
|
out_procs.back().threads += p.threads;
|
||||||
}
|
}
|
||||||
|
else children++;
|
||||||
_tree_gen(p, in_procs, out_procs, cur_depth + 1, (collapsed ? true : cache.at(cur_proc.pid).collapsed), prefix);
|
_tree_gen(p, in_procs, out_procs, cur_depth + 1, (collapsed ? true : cache.at(cur_proc.pid).collapsed), prefix);
|
||||||
}
|
}
|
||||||
if (collapsed) return;
|
if (collapsed) return;
|
||||||
|
|
||||||
if (out_procs.size() > cur_pos + 1 and not out_procs.back().prefix.ends_with("] ")) {
|
if (out_procs.size() > cur_pos + 1 and not out_procs.back().prefix.ends_with("] "))
|
||||||
out_procs.back().prefix.resize(out_procs.back().prefix.size() - 8);
|
out_procs.back().prefix.replace(out_procs.back().prefix.size() - 8, 8, " └─ ");
|
||||||
out_procs.back().prefix += " └─ ";
|
|
||||||
}
|
|
||||||
|
|
||||||
out_procs.at(cur_pos).prefix = " │ "s * cur_depth + (children > 0 ? (cache.at(cur_proc.pid).collapsed ? "[+] " : "[-] ") : prefix);
|
out_procs.at(cur_pos).prefix = " │ "s * cur_depth + (children > 0 ? (cache.at(cur_proc.pid).collapsed ? "[+] " : "[-] ") : prefix);
|
||||||
}
|
}
|
||||||
|
@ -161,12 +159,9 @@ namespace Proc {
|
||||||
string short_str;
|
string short_str;
|
||||||
auto uptime = system_uptime();
|
auto uptime = system_uptime();
|
||||||
vector<proc_info> procs;
|
vector<proc_info> procs;
|
||||||
vector<uint> pid_list;
|
|
||||||
procs.reserve((numpids + 10));
|
procs.reserve((numpids + 10));
|
||||||
pid_list.reserve(numpids + 10);
|
|
||||||
int npids = 0;
|
int npids = 0;
|
||||||
int cmult = (per_core) ? Global::coreCount : 1;
|
int cmult = (per_core) ? Global::coreCount : 1;
|
||||||
(void)tree;
|
|
||||||
|
|
||||||
//* Update uid_user map if /etc/passwd changed since last run
|
//* Update uid_user map if /etc/passwd changed since last run
|
||||||
if (not Shared::passwd_path.empty() and fs::last_write_time(Shared::passwd_path) != Shared::passwd_time) {
|
if (not Shared::passwd_path.empty() and fs::last_write_time(Shared::passwd_path) != Shared::passwd_time) {
|
||||||
|
@ -210,7 +205,6 @@ namespace Proc {
|
||||||
if (d.is_directory() and isdigit(pid_str[0])) {
|
if (d.is_directory() and isdigit(pid_str[0])) {
|
||||||
npids++;
|
npids++;
|
||||||
proc_info new_proc (stoul(pid_str));
|
proc_info new_proc (stoul(pid_str));
|
||||||
pid_list.push_back(new_proc.pid);
|
|
||||||
|
|
||||||
//* Cache program name, command and username
|
//* Cache program name, command and username
|
||||||
if (not cache.contains(new_proc.pid)) {
|
if (not cache.contains(new_proc.pid)) {
|
||||||
|
@ -225,7 +219,7 @@ namespace Proc {
|
||||||
|
|
||||||
pread.open(d.path() / "cmdline");
|
pread.open(d.path() / "cmdline");
|
||||||
if (pread.good()) {
|
if (pread.good()) {
|
||||||
string tmpstr = "";
|
string tmpstr;
|
||||||
while(getline(pread, tmpstr, '\0')) cmd += tmpstr + ' ';
|
while(getline(pread, tmpstr, '\0')) cmd += tmpstr + ' ';
|
||||||
pread.close();
|
pread.close();
|
||||||
if (not cmd.empty()) cmd.pop_back();
|
if (not cmd.empty()) cmd.pop_back();
|
||||||
|
@ -269,63 +263,69 @@ namespace Proc {
|
||||||
//* Parse /proc/[pid]/stat
|
//* Parse /proc/[pid]/stat
|
||||||
pread.open(d.path() / "stat");
|
pread.open(d.path() / "stat");
|
||||||
if (pread.good()) {
|
if (pread.good()) {
|
||||||
getline(pread, long_string);
|
|
||||||
pread.close();
|
//? Check cached name for whitespace characters and set offset to get correct fields from stat file
|
||||||
size_t s_count = 0, c_pos = 0;
|
size_t offset = rng::count(cache.at(new_proc.pid).name, ' ');
|
||||||
|
size_t x = 0, next_x = 3;
|
||||||
uint64_t cpu_t = 0;
|
uint64_t cpu_t = 0;
|
||||||
|
|
||||||
try {
|
try {
|
||||||
//? Skip pid and comm field and find comm fields closing ')'
|
while (not pread.eof()) {
|
||||||
size_t s_pos = pid_str.size() + cache.at(new_proc.pid).name.size() + 4;
|
if (++x > 40 + offset) break;
|
||||||
if (long_string.at(s_pos - 2) != ')')
|
|
||||||
s_pos = long_string.find_last_of(')') + 2;
|
|
||||||
while (s_count++ <= 37) {
|
|
||||||
c_pos = long_string.find(' ', s_pos);
|
|
||||||
if (c_pos == string::npos) break;
|
|
||||||
|
|
||||||
switch (s_count) {
|
if (x-offset < next_x) {
|
||||||
case 1: { //? Process state
|
pread.ignore(SSmax, ' ');
|
||||||
new_proc.state = long_string[s_pos];
|
continue;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
getline(pread, short_str, ' ');
|
||||||
|
|
||||||
|
switch (x-offset) {
|
||||||
|
case 3: { //? Process state
|
||||||
|
new_proc.state = short_str[0];
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
case 2: { //? Process parent pid
|
case 4: { //? Process parent pid
|
||||||
new_proc.ppid = stoull(long_string.substr(s_pos, c_pos - s_pos));
|
new_proc.ppid = stoull(short_str);
|
||||||
|
next_x = 14;
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
case 12: { //? Process utime
|
case 14: { //? Process utime
|
||||||
cpu_t = stoull(long_string.substr(s_pos, c_pos - s_pos));
|
cpu_t = stoull(short_str);
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
case 13: { //? Process stime
|
case 15: { //? Process stime
|
||||||
cpu_t += stoull(long_string.substr(s_pos, c_pos - s_pos));
|
cpu_t += stoull(short_str);
|
||||||
|
next_x = 19;
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
case 17: { //? Process nice value
|
case 19: { //? Process nice value
|
||||||
new_proc.p_nice = stoull(long_string.substr(s_pos, c_pos - s_pos));
|
new_proc.p_nice = stoull(short_str);
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
case 18: { //? Process number of threads
|
case 20: { //? Process number of threads
|
||||||
new_proc.threads = stoull(long_string.substr(s_pos, c_pos - s_pos));
|
new_proc.threads = stoull(short_str);
|
||||||
|
next_x = (new_cache) ? 22 : 40;
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
case 20: { //? Cache cpu seconds
|
case 22: { //? Cache cpu seconds
|
||||||
if (new_cache) cache[new_proc.pid].cpu_s = stoull(long_string.substr(s_pos, c_pos - s_pos));
|
cache[new_proc.pid].cpu_s = stoull(short_str);
|
||||||
|
next_x = 40;
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
case 37: { //? CPU number last executed on
|
case 40: { //? CPU number last executed on
|
||||||
new_proc.cpu_n = stoull(long_string.substr(s_pos, c_pos - s_pos));
|
new_proc.cpu_n = stoull(short_str);
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
s_pos = c_pos + 1;
|
|
||||||
}
|
}
|
||||||
|
pread.close();
|
||||||
|
|
||||||
}
|
}
|
||||||
catch (...) {
|
catch (...) {
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (s_count < 19) continue;
|
if (x-offset < 22) continue;
|
||||||
|
|
||||||
//? Process cpu usage since last update
|
//? Process cpu usage since last update
|
||||||
new_proc.cpu_p = round(cmult * 1000 * (cpu_t - cache[new_proc.pid].cpu_t) / (cputimes - old_cputimes)) / 10.0;
|
new_proc.cpu_p = round(cmult * 1000 * (cpu_t - cache[new_proc.pid].cpu_t) / (cputimes - old_cputimes)) / 10.0;
|
||||||
|
@ -366,7 +366,7 @@ namespace Proc {
|
||||||
}
|
}
|
||||||
|
|
||||||
//* When sorting with "cpu lazy" push processes over threshold cpu usage to the front regardless of cumulative usage
|
//* When sorting with "cpu lazy" push processes over threshold cpu usage to the front regardless of cumulative usage
|
||||||
if (sorting == "cpu lazy" and not tree and not reverse) {
|
if (not tree and not reverse and sorting == "cpu lazy") {
|
||||||
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 and procs[i].cpu_p > max)
|
if (i <= 5 and procs[i].cpu_p > max)
|
||||||
|
@ -388,6 +388,7 @@ namespace Proc {
|
||||||
rng::stable_sort(procs, rng::less{}, &proc_info::ppid);
|
rng::stable_sort(procs, rng::less{}, &proc_info::ppid);
|
||||||
|
|
||||||
string prefix = " ├─ ";
|
string prefix = " ├─ ";
|
||||||
|
//? Start recursive iteration over processes with the lowest shared parent pids
|
||||||
for (auto& p : rng::equal_range(procs, procs.at(0).ppid, rng::less{}, &proc_info::ppid)) {
|
for (auto& p : rng::equal_range(procs, procs.at(0).ppid, rng::less{}, &proc_info::ppid)) {
|
||||||
_tree_gen(p, procs, tree_procs, 0, cache.at(p.pid).collapsed, prefix);
|
_tree_gen(p, procs, tree_procs, 0, cache.at(p.pid).collapsed, prefix);
|
||||||
}
|
}
|
||||||
|
@ -399,8 +400,11 @@ namespace Proc {
|
||||||
if (++counter >= 10000 or ((int)cache.size() > npids + 100)) {
|
if (++counter >= 10000 or ((int)cache.size() > npids + 100)) {
|
||||||
counter = 0;
|
counter = 0;
|
||||||
unordered_flat_map<uint, p_cache> r_cache;
|
unordered_flat_map<uint, p_cache> r_cache;
|
||||||
r_cache.reserve(pid_list.size());
|
r_cache.reserve(procs.size());
|
||||||
rng::for_each(pid_list, [&r_cache](const auto &p){ if (cache.contains(p)) r_cache[p] = cache.at(p); });
|
rng::for_each(procs, [&r_cache](const auto &p){
|
||||||
|
if (cache.contains(p.pid))
|
||||||
|
r_cache[p.pid] = cache.at(p.pid);
|
||||||
|
});
|
||||||
cache.swap(r_cache);
|
cache.swap(r_cache);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
Loading…
Reference in New Issue