mirror of
https://github.com/aristocratos/btop.git
synced 2024-09-28 22:21:35 +02:00
Removed bad goto and added 100 microseconds sleep in thread manager loop to spare some cpu cycles
This commit is contained in:
parent
f9ed675d47
commit
ced3d47ebe
32
src/btop.cpp
32
src/btop.cpp
@ -347,10 +347,10 @@ namespace Runner {
|
|||||||
|
|
||||||
//* Start collection functions for all boxes in async threads and draw in this thread when finished
|
//* Start collection functions for all boxes in async threads and draw in this thread when finished
|
||||||
//? Starting order below based on mean time to finish
|
//? Starting order below based on mean time to finish
|
||||||
while (box_mask.count() > 0) {
|
try {
|
||||||
if (stopping) break;
|
while (box_mask.count() > 0) {
|
||||||
try {
|
if (stopping) break;
|
||||||
//* PROC
|
//? PROC
|
||||||
if (box_mask.test(proc_present)) {
|
if (box_mask.test(proc_present)) {
|
||||||
if (not box_mask.test(proc_running)) {
|
if (not box_mask.test(proc_running)) {
|
||||||
proc = async(Proc::collect, conf->no_update);
|
proc = async(Proc::collect, conf->no_update);
|
||||||
@ -367,9 +367,10 @@ namespace Runner {
|
|||||||
throw std::runtime_error("Proc:: -> " + (string)e.what());
|
throw std::runtime_error("Proc:: -> " + (string)e.what());
|
||||||
}
|
}
|
||||||
box_mask ^= proc_done;
|
box_mask ^= proc_done;
|
||||||
|
continue;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
//* MEM
|
//? MEM
|
||||||
if (box_mask.test(mem_present)) {
|
if (box_mask.test(mem_present)) {
|
||||||
if (not box_mask.test(mem_running)) {
|
if (not box_mask.test(mem_running)) {
|
||||||
mem = async(Mem::collect, conf->no_update);
|
mem = async(Mem::collect, conf->no_update);
|
||||||
@ -386,9 +387,10 @@ namespace Runner {
|
|||||||
throw std::runtime_error("Mem:: -> " + (string)e.what());
|
throw std::runtime_error("Mem:: -> " + (string)e.what());
|
||||||
}
|
}
|
||||||
box_mask ^= mem_done;
|
box_mask ^= mem_done;
|
||||||
|
continue;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
//* NET
|
//? NET
|
||||||
if (box_mask.test(net_present)) {
|
if (box_mask.test(net_present)) {
|
||||||
if (not box_mask.test(net_running)) {
|
if (not box_mask.test(net_running)) {
|
||||||
net = async(Net::collect, conf->no_update);
|
net = async(Net::collect, conf->no_update);
|
||||||
@ -405,9 +407,10 @@ namespace Runner {
|
|||||||
throw std::runtime_error("Net:: -> " + (string)e.what());
|
throw std::runtime_error("Net:: -> " + (string)e.what());
|
||||||
}
|
}
|
||||||
box_mask ^= net_done;
|
box_mask ^= net_done;
|
||||||
|
continue;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
//* CPU
|
//? CPU
|
||||||
if (box_mask.test(cpu_present)) {
|
if (box_mask.test(cpu_present)) {
|
||||||
if (not box_mask.test(cpu_running)) {
|
if (not box_mask.test(cpu_running)) {
|
||||||
cpu = async(Cpu::collect, conf->no_update);
|
cpu = async(Cpu::collect, conf->no_update);
|
||||||
@ -424,16 +427,17 @@ namespace Runner {
|
|||||||
throw std::runtime_error("Cpu:: -> " + (string)e.what());
|
throw std::runtime_error("Cpu:: -> " + (string)e.what());
|
||||||
}
|
}
|
||||||
box_mask ^= cpu_done;
|
box_mask ^= cpu_done;
|
||||||
|
continue;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
sleep_micros(100);
|
||||||
}
|
}
|
||||||
catch (const std::exception& e) {
|
}
|
||||||
Global::exit_error_msg = "Exception in runner thread -> " + (string)e.what();
|
catch (const std::exception& e) {
|
||||||
Global::thread_exception = true;
|
Global::exit_error_msg = "Exception in runner thread -> " + (string)e.what();
|
||||||
Input::interrupt = true;
|
Global::thread_exception = true;
|
||||||
stopping = true;
|
Input::interrupt = true;
|
||||||
break;
|
stopping = true;
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
if (stopping) {
|
if (stopping) {
|
||||||
|
@ -962,8 +962,9 @@ namespace Proc {
|
|||||||
if (item_fit >= 4) out += cjust("IO/W:", item_width);
|
if (item_fit >= 4) out += cjust("IO/W:", item_width);
|
||||||
if (item_fit >= 5) out += cjust("Parent:", item_width);
|
if (item_fit >= 5) out += cjust("Parent:", item_width);
|
||||||
if (item_fit >= 6) out += cjust("User:", item_width);
|
if (item_fit >= 6) out += cjust("User:", item_width);
|
||||||
if (item_fit >= 7) out += cjust("Nice:", item_width);
|
if (item_fit >= 7) out += cjust("Threads:", item_width);
|
||||||
if (item_fit >= 8) out += cjust("Threads:", item_width);
|
if (item_fit >= 8) out += cjust("Nice:", item_width);
|
||||||
|
|
||||||
|
|
||||||
//? Command line
|
//? Command line
|
||||||
for (int i = 0; const auto& l : {'C', 'M', 'D'})
|
for (int i = 0; const auto& l : {'C', 'M', 'D'})
|
||||||
@ -1084,8 +1085,9 @@ namespace Proc {
|
|||||||
if (item_fit >= 4) out += cjust(detailed.io_write, item_width);
|
if (item_fit >= 4) out += cjust(detailed.io_write, item_width);
|
||||||
if (item_fit >= 5) out += cjust(detailed.parent, item_width, true);
|
if (item_fit >= 5) out += cjust(detailed.parent, item_width, true);
|
||||||
if (item_fit >= 6) out += cjust(detailed.entry.user, item_width, true);
|
if (item_fit >= 6) out += cjust(detailed.entry.user, item_width, true);
|
||||||
if (item_fit >= 7) out += cjust(to_string(detailed.entry.p_nice), item_width);
|
if (item_fit >= 7) out += cjust(to_string(detailed.entry.threads), item_width);
|
||||||
if (item_fit >= 8) out += cjust(to_string(detailed.entry.threads), item_width);
|
if (item_fit >= 8) out += cjust(to_string(detailed.entry.p_nice), item_width);
|
||||||
|
|
||||||
|
|
||||||
const double mem_p = (double)detailed.mem_bytes.back() * 100 / Shared::totalMem;
|
const double mem_p = (double)detailed.mem_bytes.back() * 100 / Shared::totalMem;
|
||||||
string mem_str = to_string(mem_p);
|
string mem_str = to_string(mem_p);
|
||||||
|
@ -1000,214 +1000,216 @@ namespace Proc {
|
|||||||
procs.reserve(current_procs.size() + 10);
|
procs.reserve(current_procs.size() + 10);
|
||||||
const int cmult = (per_core) ? Shared::coreCount : 1;
|
const int cmult = (per_core) ? Shared::coreCount : 1;
|
||||||
bool got_detailed = false;
|
bool got_detailed = false;
|
||||||
|
|
||||||
|
//* Use pids from last update if only changing filter, sorting or tree options
|
||||||
if (no_update and not cache.empty()) {
|
if (no_update and not cache.empty()) {
|
||||||
procs = current_procs;
|
procs = current_procs;
|
||||||
if (show_detailed and detailed_pid != detailed.last_pid) _collect_details(detailed_pid, round(uptime), procs);
|
if (show_detailed and detailed_pid != detailed.last_pid) _collect_details(detailed_pid, round(uptime), procs);
|
||||||
goto proc_no_update;
|
|
||||||
}
|
}
|
||||||
|
//* ---------------------------------------------Collection start----------------------------------------------
|
||||||
//? Update uid_user map if /etc/passwd changed since last run
|
else {
|
||||||
if (not Shared::passwd_path.empty() and fs::last_write_time(Shared::passwd_path) != passwd_time) {
|
//? Update uid_user map if /etc/passwd changed since last run
|
||||||
string r_uid, r_user;
|
if (not Shared::passwd_path.empty() and fs::last_write_time(Shared::passwd_path) != passwd_time) {
|
||||||
passwd_time = fs::last_write_time(Shared::passwd_path);
|
string r_uid, r_user;
|
||||||
uid_user.clear();
|
passwd_time = fs::last_write_time(Shared::passwd_path);
|
||||||
pread.open(Shared::passwd_path);
|
uid_user.clear();
|
||||||
if (pread.good()) {
|
pread.open(Shared::passwd_path);
|
||||||
while (not pread.eof()) {
|
if (pread.good()) {
|
||||||
getline(pread, r_user, ':');
|
while (not pread.eof()) {
|
||||||
pread.ignore(SSmax, ':');
|
getline(pread, r_user, ':');
|
||||||
getline(pread, r_uid, ':');
|
pread.ignore(SSmax, ':');
|
||||||
uid_user[r_uid] = r_user;
|
getline(pread, r_uid, ':');
|
||||||
pread.ignore(SSmax, '\n');
|
uid_user[r_uid] = r_user;
|
||||||
}
|
|
||||||
}
|
|
||||||
else {
|
|
||||||
Shared::passwd_path.clear();
|
|
||||||
}
|
|
||||||
pread.close();
|
|
||||||
}
|
|
||||||
|
|
||||||
//* Get cpu total times from /proc/stat
|
|
||||||
cputimes = 0;
|
|
||||||
pread.open(Shared::procPath / "stat");
|
|
||||||
if (pread.good()) {
|
|
||||||
pread.ignore(SSmax, ' ');
|
|
||||||
for (uint64_t times; pread >> times; cputimes += times);
|
|
||||||
pread.close();
|
|
||||||
}
|
|
||||||
else throw std::runtime_error("Failure to read /proc/stat");
|
|
||||||
|
|
||||||
//* Iterate over all pids in /proc
|
|
||||||
for (const auto& d: fs::directory_iterator(Shared::procPath)) {
|
|
||||||
if (Runner::stopping)
|
|
||||||
return procs;
|
|
||||||
if (pread.is_open()) pread.close();
|
|
||||||
|
|
||||||
const string pid_str = d.path().filename();
|
|
||||||
if (not isdigit(pid_str[0])) continue;
|
|
||||||
|
|
||||||
proc_info new_proc (stoul(pid_str));
|
|
||||||
|
|
||||||
//* Cache program name, command and username
|
|
||||||
if (not cache.contains(new_proc.pid)) {
|
|
||||||
string name, cmd, user;
|
|
||||||
pread.open(d.path() / "comm");
|
|
||||||
if (not pread.good()) continue;
|
|
||||||
getline(pread, name);
|
|
||||||
pread.close();
|
|
||||||
size_t name_offset = rng::count(name, ' ');
|
|
||||||
|
|
||||||
pread.open(d.path() / "cmdline");
|
|
||||||
if (not pread.good()) continue;
|
|
||||||
long_string.clear();
|
|
||||||
while(getline(pread, long_string, '\0')) cmd += long_string + ' ';
|
|
||||||
pread.close();
|
|
||||||
if (not cmd.empty()) cmd.pop_back();
|
|
||||||
|
|
||||||
pread.open(d.path() / "status");
|
|
||||||
if (not pread.good()) continue;
|
|
||||||
string uid;
|
|
||||||
string line;
|
|
||||||
while (not pread.eof()) {
|
|
||||||
getline(pread, line, ':');
|
|
||||||
if (line == "Uid") {
|
|
||||||
pread.ignore();
|
|
||||||
getline(pread, uid, '\t');
|
|
||||||
break;
|
|
||||||
} else {
|
|
||||||
pread.ignore(SSmax, '\n');
|
pread.ignore(SSmax, '\n');
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
else {
|
||||||
|
Shared::passwd_path.clear();
|
||||||
|
}
|
||||||
pread.close();
|
pread.close();
|
||||||
user = (uid_user.contains(uid)) ? uid_user.at(uid) : uid;
|
|
||||||
|
|
||||||
cache[new_proc.pid] = {name, cmd, user, name_offset};
|
|
||||||
}
|
}
|
||||||
|
|
||||||
new_proc.name = cache.at(new_proc.pid).name;
|
//? Get cpu total times from /proc/stat
|
||||||
new_proc.cmd = cache.at(new_proc.pid).cmd;
|
cputimes = 0;
|
||||||
new_proc.user = cache.at(new_proc.pid).user;
|
pread.open(Shared::procPath / "stat");
|
||||||
|
if (pread.good()) {
|
||||||
|
pread.ignore(SSmax, ' ');
|
||||||
|
for (uint64_t times; pread >> times; cputimes += times);
|
||||||
|
pread.close();
|
||||||
|
}
|
||||||
|
else throw std::runtime_error("Failure to read /proc/stat");
|
||||||
|
|
||||||
//* Parse /proc/[pid]/stat
|
//? Iterate over all pids in /proc
|
||||||
pread.open(d.path() / "stat");
|
for (const auto& d: fs::directory_iterator(Shared::procPath)) {
|
||||||
if (not pread.good()) continue;
|
if (Runner::stopping)
|
||||||
|
return procs;
|
||||||
|
if (pread.is_open()) pread.close();
|
||||||
|
|
||||||
//? Check cached value for whitespace characters in name and set offset to get correct fields from stat file
|
const string pid_str = d.path().filename();
|
||||||
size_t& offset = cache.at(new_proc.pid).name_offset;
|
if (not isdigit(pid_str[0])) continue;
|
||||||
short_str.clear();
|
|
||||||
size_t x = 0, next_x = 3;
|
|
||||||
uint64_t cpu_t = 0;
|
|
||||||
try {
|
|
||||||
for (;;) {
|
|
||||||
while (pread.good() and ++x - offset < next_x) {
|
|
||||||
pread.ignore(SSmax, ' ');
|
|
||||||
}
|
|
||||||
if (pread.bad()) goto stat_loop_done;
|
|
||||||
|
|
||||||
getline(pread, short_str, ' ');
|
proc_info new_proc (stoul(pid_str));
|
||||||
|
|
||||||
switch (x-offset) {
|
//? Cache program name, command and username
|
||||||
case 3: { //? Process state
|
if (not cache.contains(new_proc.pid)) {
|
||||||
new_proc.state = short_str.at(0);
|
string name, cmd, user;
|
||||||
continue;
|
pread.open(d.path() / "comm");
|
||||||
}
|
if (not pread.good()) continue;
|
||||||
case 4: { //? Parent pid
|
getline(pread, name);
|
||||||
new_proc.ppid = stoull(short_str);
|
pread.close();
|
||||||
next_x = 14;
|
size_t name_offset = rng::count(name, ' ');
|
||||||
continue;
|
|
||||||
}
|
pread.open(d.path() / "cmdline");
|
||||||
case 14: { //? Process utime
|
if (not pread.good()) continue;
|
||||||
cpu_t = stoull(short_str);
|
long_string.clear();
|
||||||
continue;
|
while(getline(pread, long_string, '\0')) cmd += long_string + ' ';
|
||||||
}
|
pread.close();
|
||||||
case 15: { //? Process stime
|
if (not cmd.empty()) cmd.pop_back();
|
||||||
cpu_t += stoull(short_str);
|
|
||||||
next_x = 19;
|
pread.open(d.path() / "status");
|
||||||
continue;
|
if (not pread.good()) continue;
|
||||||
}
|
string uid;
|
||||||
case 19: { //? Nice value
|
string line;
|
||||||
new_proc.p_nice = stoull(short_str);
|
while (not pread.eof()) {
|
||||||
continue;
|
getline(pread, line, ':');
|
||||||
}
|
if (line == "Uid") {
|
||||||
case 20: { //? Number of threads
|
pread.ignore();
|
||||||
new_proc.threads = stoull(short_str);
|
getline(pread, uid, '\t');
|
||||||
if (cache.at(new_proc.pid).cpu_s == 0) {
|
break;
|
||||||
next_x = 22;
|
} else {
|
||||||
cache.at(new_proc.pid).cpu_t = cpu_t;
|
pread.ignore(SSmax, '\n');
|
||||||
}
|
|
||||||
else
|
|
||||||
next_x = 24;
|
|
||||||
continue;
|
|
||||||
}
|
|
||||||
case 22: { //? Save cpu seconds to cache if missing
|
|
||||||
cache.at(new_proc.pid).cpu_s = stoull(short_str);
|
|
||||||
next_x = 24;
|
|
||||||
continue;
|
|
||||||
}
|
|
||||||
case 24: { //? RSS memory (can be inaccurate, but parsing smaps increases total cpu usage by ~20x)
|
|
||||||
new_proc.mem = stoull(short_str) * Shared::pageSize;
|
|
||||||
next_x = 39;
|
|
||||||
continue;
|
|
||||||
}
|
|
||||||
case 39: { //? CPU number last executed on
|
|
||||||
new_proc.cpu_n = stoull(short_str);
|
|
||||||
goto stat_loop_done;
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
pread.close();
|
||||||
|
user = (uid_user.contains(uid)) ? uid_user.at(uid) : uid;
|
||||||
|
|
||||||
|
cache[new_proc.pid] = {name, cmd, user, name_offset};
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
new_proc.name = cache.at(new_proc.pid).name;
|
||||||
catch (const std::invalid_argument&) { continue; }
|
new_proc.cmd = cache.at(new_proc.pid).cmd;
|
||||||
catch (const std::out_of_range&) { continue; }
|
new_proc.user = cache.at(new_proc.pid).user;
|
||||||
|
|
||||||
stat_loop_done:
|
//? Parse /proc/[pid]/stat
|
||||||
pread.close();
|
pread.open(d.path() / "stat");
|
||||||
|
if (not pread.good()) continue;
|
||||||
|
|
||||||
if (x-offset < 24) continue;
|
//? Check cached value for whitespace characters in name and set offset to get correct fields from stat file
|
||||||
|
size_t& offset = cache.at(new_proc.pid).name_offset;
|
||||||
|
short_str.clear();
|
||||||
|
size_t x = 0, next_x = 3;
|
||||||
|
uint64_t cpu_t = 0;
|
||||||
|
try {
|
||||||
|
for (;;) {
|
||||||
|
while (pread.good() and ++x - offset < next_x) {
|
||||||
|
pread.ignore(SSmax, ' ');
|
||||||
|
}
|
||||||
|
if (pread.bad()) goto stat_loop_done;
|
||||||
|
|
||||||
//? Process cpu usage since last update
|
getline(pread, short_str, ' ');
|
||||||
new_proc.cpu_p = round(cmult * 1000 * (cpu_t - cache.at(new_proc.pid).cpu_t) / max(1ul, cputimes - old_cputimes)) / 10.0;
|
|
||||||
|
|
||||||
//? Process cumulative cpu usage since process start
|
switch (x-offset) {
|
||||||
new_proc.cpu_c = (double)cpu_t / max(1.0, (uptime * Shared::clkTck) - cache.at(new_proc.pid).cpu_s);
|
case 3: { //? Process state
|
||||||
|
new_proc.state = short_str.at(0);
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
case 4: { //? Parent pid
|
||||||
|
new_proc.ppid = stoull(short_str);
|
||||||
|
next_x = 14;
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
case 14: { //? Process utime
|
||||||
|
cpu_t = stoull(short_str);
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
case 15: { //? Process stime
|
||||||
|
cpu_t += stoull(short_str);
|
||||||
|
next_x = 19;
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
case 19: { //? Nice value
|
||||||
|
new_proc.p_nice = stoull(short_str);
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
case 20: { //? Number of threads
|
||||||
|
new_proc.threads = stoull(short_str);
|
||||||
|
if (cache.at(new_proc.pid).cpu_s == 0) {
|
||||||
|
next_x = 22;
|
||||||
|
cache.at(new_proc.pid).cpu_t = cpu_t;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
next_x = 24;
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
case 22: { //? Save cpu seconds to cache if missing
|
||||||
|
cache.at(new_proc.pid).cpu_s = stoull(short_str);
|
||||||
|
next_x = 24;
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
case 24: { //? RSS memory (can be inaccurate, but parsing smaps increases total cpu usage by ~20x)
|
||||||
|
new_proc.mem = stoull(short_str) * Shared::pageSize;
|
||||||
|
next_x = 39;
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
case 39: { //? CPU number last executed on
|
||||||
|
new_proc.cpu_n = stoull(short_str);
|
||||||
|
goto stat_loop_done;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
//? Update cache with latest cpu times
|
}
|
||||||
cache.at(new_proc.pid).cpu_t = cpu_t;
|
catch (const std::invalid_argument&) { continue; }
|
||||||
|
catch (const std::out_of_range&) { continue; }
|
||||||
|
|
||||||
|
stat_loop_done:
|
||||||
|
pread.close();
|
||||||
|
|
||||||
|
if (x-offset < 24) continue;
|
||||||
|
|
||||||
|
//? Process cpu usage since last update
|
||||||
|
new_proc.cpu_p = round(cmult * 1000 * (cpu_t - cache.at(new_proc.pid).cpu_t) / max(1ul, cputimes - old_cputimes)) / 10.0;
|
||||||
|
|
||||||
|
//? Process cumulative cpu usage since process start
|
||||||
|
new_proc.cpu_c = (double)cpu_t / max(1.0, (uptime * Shared::clkTck) - cache.at(new_proc.pid).cpu_s);
|
||||||
|
|
||||||
|
//? Update cache with latest cpu times
|
||||||
|
cache.at(new_proc.pid).cpu_t = cpu_t;
|
||||||
|
|
||||||
|
if (show_detailed and not got_detailed and new_proc.pid == detailed_pid) {
|
||||||
|
got_detailed = true;
|
||||||
|
}
|
||||||
|
|
||||||
|
//? Push process to vector
|
||||||
|
procs.push_back(new_proc);
|
||||||
|
|
||||||
if (show_detailed and not got_detailed and new_proc.pid == detailed_pid) {
|
|
||||||
got_detailed = true;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
//? Push process to vector
|
//? Clear dead processes from cache at a regular interval
|
||||||
procs.push_back(new_proc);
|
if (++counter >= 1000 or (cache.size() > procs.size() + 100)) {
|
||||||
|
counter = 0;
|
||||||
|
unordered_flat_map<size_t, p_cache> r_cache;
|
||||||
|
r_cache.reserve(procs.size());
|
||||||
|
rng::for_each(procs, [&r_cache](const auto &p) {
|
||||||
|
if (cache.contains(p.pid))
|
||||||
|
r_cache[p.pid] = cache.at(p.pid);
|
||||||
|
});
|
||||||
|
cache = std::move(r_cache);
|
||||||
|
}
|
||||||
|
|
||||||
|
//? Update the details info box for process if active
|
||||||
|
if (show_detailed and got_detailed) {
|
||||||
|
_collect_details(detailed_pid, round(uptime), procs);
|
||||||
|
}
|
||||||
|
else if (show_detailed and not got_detailed and detailed.status != "Dead") {
|
||||||
|
detailed.status = "Dead";
|
||||||
|
redraw = true;
|
||||||
|
}
|
||||||
|
|
||||||
|
old_cputimes = cputimes;
|
||||||
|
current_procs = procs;
|
||||||
}
|
}
|
||||||
|
//* ---------------------------------------------Collection done-----------------------------------------------
|
||||||
//* Clear dead processes from cache at a regular interval
|
|
||||||
if (++counter >= 1000 or (cache.size() > procs.size() + 100)) {
|
|
||||||
counter = 0;
|
|
||||||
unordered_flat_map<size_t, p_cache> r_cache;
|
|
||||||
r_cache.reserve(procs.size());
|
|
||||||
rng::for_each(procs, [&r_cache](const auto &p) {
|
|
||||||
if (cache.contains(p.pid))
|
|
||||||
r_cache[p.pid] = cache.at(p.pid);
|
|
||||||
});
|
|
||||||
cache = std::move(r_cache);
|
|
||||||
}
|
|
||||||
|
|
||||||
//* Update the details info box for process if active
|
|
||||||
if (show_detailed and got_detailed) {
|
|
||||||
_collect_details(detailed_pid, round(uptime), procs);
|
|
||||||
}
|
|
||||||
else if (show_detailed and not got_detailed and detailed.status != "Dead") {
|
|
||||||
detailed.status = "Dead";
|
|
||||||
redraw = true;
|
|
||||||
}
|
|
||||||
|
|
||||||
old_cputimes = cputimes;
|
|
||||||
current_procs = procs;
|
|
||||||
|
|
||||||
proc_no_update:
|
|
||||||
|
|
||||||
//* Match filter if defined
|
//* Match filter if defined
|
||||||
if (not tree and not filter.empty()) {
|
if (not tree and not filter.empty()) {
|
||||||
|
@ -229,6 +229,9 @@ namespace Tools {
|
|||||||
//* Put current thread to sleep for <ms> milliseconds
|
//* Put current thread to sleep for <ms> milliseconds
|
||||||
inline void sleep_ms(const size_t& ms) { std::this_thread::sleep_for(std::chrono::milliseconds(ms)); }
|
inline void sleep_ms(const size_t& ms) { std::this_thread::sleep_for(std::chrono::milliseconds(ms)); }
|
||||||
|
|
||||||
|
//* Put current thread to sleep for <micros> microseconds
|
||||||
|
inline void sleep_micros(const size_t& micros) { std::this_thread::sleep_for(std::chrono::microseconds(micros)); }
|
||||||
|
|
||||||
//* Left justify string <str> if <x> is greater than <str> length, limit return size to <x> by default
|
//* Left justify string <str> if <x> is greater than <str> length, limit return size to <x> by default
|
||||||
string ljust(string str, const size_t x, const bool utf=false, const bool wide=false, const bool limit=true);
|
string ljust(string str, const size_t x, const bool utf=false, const bool wide=false, const bool limit=true);
|
||||||
|
|
||||||
|
Loading…
Reference in New Issue
Block a user