Skip to content
Open
Show file tree
Hide file tree
Changes from 5 commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
8 changes: 7 additions & 1 deletion src/btop_config.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -104,7 +104,7 @@ namespace Config {

{"update_ms", "#* Update time in milliseconds, recommended 2000 ms or above for better sample times for graphs."},

{"proc_sorting", "#* Processes sorting, \"pid\" \"program\" \"arguments\" \"threads\" \"user\" \"memory\" \"cpu lazy\" \"cpu direct\",\n"
{"proc_sorting", "#* Processes sorting, \"pid\" \"program\" \"arguments\" \"threads\" \"user\" \"memory\" \"gpu\" \"gpu memory\" \"cpu lazy\" \"cpu direct\",\n"
"#* \"cpu lazy\" sorts top process over time (easier to follow), \"cpu direct\" updates top process directly."},

{"proc_reversed", "#* Reverse sorting order, True or False."},
Expand All @@ -121,6 +121,10 @@ namespace Config {

{"proc_cpu_graphs", "#* Show cpu graph for each process."},

{"proc_gpu_graphs", "#* Show gpu graph for each process."},

{"proc_gpu_only", "#* Show only processes with active GPU usage or GPU memory allocation in the process list."},

{"proc_info_smaps", "#* Use /proc/[pid]/smaps for memory information in the process info box (very slow but more accurate)"},

{"proc_left", "#* Show proc box on left side of screen instead of right."},
Expand Down Expand Up @@ -304,6 +308,8 @@ namespace Config {
{"proc_per_core", false},
{"proc_mem_bytes", true},
{"proc_cpu_graphs", true},
{"proc_gpu_graphs", true},
{"proc_gpu_only", false},
{"proc_info_smaps", false},
{"proc_left", false},
{"proc_filter_kernel", false},
Expand Down
95 changes: 81 additions & 14 deletions src/btop_draw.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -1577,8 +1577,10 @@ namespace Proc {
int scroll_pos;
string selected_name;
std::unordered_map<size_t, Draw::Graph> p_graphs;
std::unordered_map<size_t, Draw::Graph> p_graphs_gpu;
std::unordered_map<size_t, bool> p_wide_cmd;
std::unordered_map<size_t, int> p_counters;
std::unordered_map<size_t, int> p_counters_gpu;
int counter = 0;
Draw::TextEdit filter;
Draw::Graph detailed_cpu_graph;
Expand Down Expand Up @@ -1681,7 +1683,15 @@ namespace Proc {
auto& graph_bg = Symbols::graph_symbols.at((graph_symbol == "default" ? Config::getS("graph_symbol") + "_up" : graph_symbol + "_up")).at(6);
auto mem_bytes = Config::getB("proc_mem_bytes");
auto vim_keys = Config::getB("vim_keys");
auto show_graphs = Config::getB("proc_cpu_graphs");
auto show_cpu_graphs = Config::getB("proc_cpu_graphs");
auto show_gpu_graphs = Config::getB("proc_gpu_graphs");
#if defined(__linux__)
const bool show_gpu = width >= ((show_cpu_graphs or show_gpu_graphs) ? 70 : 65);
const bool show_gpu_mem = width >= ((show_cpu_graphs or show_gpu_graphs) ? 78 : 73);
#else
const bool show_gpu = false;
const bool show_gpu_mem = false;
#endif
const auto pause_proc_list = Config::getB("pause_proc_list");
auto follow_process = Config::getB("follow_process");
int followed_pid = Config::getI("followed_pid");
Expand Down Expand Up @@ -1772,10 +1782,14 @@ namespace Proc {
//? Adapt sizes of text fields
user_size = (width < 75 ? 5 : 10);
thread_size = (width < 75 ? - 1 : 4);
prog_size = (width > 70 ? 16 : ( width > 55 ? 8 : width - user_size - thread_size - 33));
cmd_size = (width > 55 ? width - prog_size - user_size - thread_size - 33 : -1);
tree_size = width - user_size - thread_size - 23;
if (not show_graphs) {
const int gpu_cols = (show_gpu_mem ? 6 : 0) + (show_gpu ? 6 : 0);
const int gpu_graph_cols = (show_gpu and show_gpu_graphs ? 5 : 0);
const int proc_fixed = 33 + gpu_cols + gpu_graph_cols;
const int tree_fixed = 23 + gpu_cols + gpu_graph_cols;
prog_size = (width > 70 ? 16 : ( width > 55 ? 8 : width - user_size - thread_size - proc_fixed));
cmd_size = (width > 55 ? width - prog_size - user_size - thread_size - proc_fixed : -1);
tree_size = width - user_size - thread_size - tree_fixed;
if (not show_cpu_graphs) {
cmd_size += 5;
tree_size += 5;
}
Expand Down Expand Up @@ -1880,15 +1894,24 @@ namespace Proc {

//? pause, per-core, reverse, tree and sorting
const auto& sorting = Config::getS("proc_sorting");
const auto gpu_only = Config::getB("proc_gpu_only");
const int sort_len = sorting.size();
const int sort_pos = x + width - sort_len - 8;

if (width > 70 + sort_len) {
fmt::format_to(std::back_inserter(out), "{}{}{}{}{}{}{}{}{}{}{}",
Mv::to(y, sort_pos - 43), title_left, gpu_only ? Fx::b : "",
Theme::c("hi_fg"), 'g', Theme::c("title"), "pu-",
Theme::c("title"), "only",
Fx::ub, title_right);
Input::mouse_mappings["g"] = {y, sort_pos - 42, 1, 8};
}
if (width > 60 + sort_len) {
fmt::format_to(std::back_inserter(out), "{}{}{}{}{}{}{}{}{}{}{}",
fmt::format_to(std::back_inserter(out), "{}{}{}{}{}{}{}{}{}{}{}",
Mv::to(y, sort_pos - 32), title_left, pause_proc_list ? Fx::b : "",
Theme::c("title"), "pa", Theme::c("hi_fg"), 'u', Theme::c("title"), "se",
Fx::ub, title_right);
Input::mouse_mappings["u"] = {y, sort_pos - 31, 1, 5};
Fx::ub, title_right);
Input::mouse_mappings["u"] = {y, sort_pos - 31, 1, 5};
}
if (width > 55 + sort_len) {
out += Mv::to(y, sort_pos - 25) + title_left + (Config::getB("proc_per_core") ? Fx::b : "") + Theme::c("title")
Expand Down Expand Up @@ -1958,7 +1981,10 @@ namespace Proc {
out += (thread_size > 0 ? Mv::l(4) + "Threads: " : "")
+ ljust("User:", user_size) + ' '
+ rjust((mem_bytes ? "MemB" : "Mem%"), 5) + ' '
+ rjust("Cpu%", (show_graphs ? 10 : 5)) + Fx::ub;
+ rjust("Cpu%", (show_cpu_graphs ? 10 : 5))
+ (show_gpu_mem ? string{" "} + rjust("GMem", 5) : "")
+ (show_gpu ? string{" "} + rjust("Gpu%", (show_gpu_graphs ? 10 : 5)) : "")
+ Fx::ub;
}
//* End of redraw block

Expand Down Expand Up @@ -2021,9 +2047,9 @@ namespace Proc {
selected_depth = p.depth;
}

//? Update graphs for processes with above 0.0% cpu usage, delete if below 0.1% 10x times
bool has_graph = show_graphs ? p_counters.contains(p.pid) : false;
if (show_graphs and ((p.cpu_p > 0 and not has_graph) or (not data_same and has_graph))) {
//? Update cpu graphs for processes with above 0.0% cpu usage, delete if below 0.1% 10x times
bool has_graph = show_cpu_graphs ? p_counters.contains(p.pid) : false;
if (show_cpu_graphs and ((p.cpu_p > 0 and not has_graph) or (not data_same and has_graph))) {
if (not has_graph) {
p_graphs[p.pid] = Draw::Graph{5, 1, "", {}, graph_symbol};
p_counters[p.pid] = 0;
Expand All @@ -2036,6 +2062,21 @@ namespace Proc {
p_counters[p.pid] = 0;
}

//? Update gpu graphs for processes with above 0.0% gpu usage, delete if below 0.1% 10x times
bool has_gpu_graph = (show_gpu and show_gpu_graphs) ? p_counters_gpu.contains(p.pid) : false;
if ((show_gpu and show_gpu_graphs) and ((p.gpu_p > 0 and not has_gpu_graph) or (not data_same and has_gpu_graph))) {
if (not has_gpu_graph) {
p_graphs_gpu[p.pid] = Draw::Graph{5, 1, "", {}, graph_symbol};
p_counters_gpu[p.pid] = 0;
}
else if (p.gpu_p < 0.1 and ++p_counters_gpu[p.pid] >= 10) {
if (p_graphs_gpu.contains(p.pid)) p_graphs_gpu.erase(p.pid);
p_counters_gpu.erase(p.pid);
}
else
p_counters_gpu[p.pid] = 0;
}

out += Fx::reset;

//? Set correct gradient colors if enabled
Expand Down Expand Up @@ -2110,6 +2151,18 @@ namespace Proc {
if (cpu_str.ends_with('.')) cpu_str.pop_back();
cpu_str += "k";
}
string gpu_str;
if (show_gpu) {
if (p.gpu_p <= 0.0 and p.gpu_m == 0) {
gpu_str = "-";
}
else {
gpu_str = fmt::format("{:.1f}", clamp(p.gpu_p, 0.0, 100.0));
if (gpu_str.size() > 4) gpu_str.resize(4);
if (gpu_str.ends_with('.')) gpu_str.pop_back();
}
}
const string gpu_mem_str = show_gpu_mem ? (p.gpu_p <= 0.0 and p.gpu_m == 0 ? "-" : floating_humanizer(p.gpu_m, true)) : "";
Comment thread
KinanLak marked this conversation as resolved.
Outdated
string mem_str = (mem_bytes ? floating_humanizer(p.mem, true) : "");
if (not mem_bytes) {
double mem_p = clamp((double)p.mem * 100 / totalMem, 0.0, 100.0);
Expand All @@ -2131,9 +2184,13 @@ namespace Proc {
out += (thread_size > 0 ? t_color + rjust(proc_threads_string, thread_size) + ' ' + end : "" )
+ g_color + ljust((cmp_greater(p.user.size(), user_size) ? p.user.substr(0, user_size - 1) + '+' : p.user), user_size) + ' '
+ m_color + rjust(mem_str, 5) + end + ' '
+ (is_selected or is_followed ? "" : Theme::c("inactive_fg")) + (show_graphs ? graph_bg * 5: "")
+ (is_selected or is_followed ? "" : Theme::c("inactive_fg")) + (show_cpu_graphs ? graph_bg * 5: "")
+ (p_graphs.contains(p.pid) ? Mv::l(5) + c_color + p_graphs.at(p.pid)({(p.cpu_p >= 0.1 and p.cpu_p < 5 ? 5ll : (long long)round(p.cpu_p))}, data_same) : "") + end + ' '
+ c_color + rjust(cpu_str, 4) + " " + end;
+ c_color + rjust(cpu_str, 4) + ' ' + end
+ (show_gpu_mem ? c_color + rjust(gpu_mem_str, 5) + ' ' + end : "")
+ (is_selected or is_followed ? "" : Theme::c("inactive_fg")) + ((show_gpu and show_gpu_graphs) ? graph_bg * 5 : "")
+ (p_graphs_gpu.contains(p.pid) ? Mv::l(5) + c_color + p_graphs_gpu.at(p.pid)({(p.gpu_p >= 0.1 and p.gpu_p < 5 ? 5ll : (long long)round(p.gpu_p))}, data_same) : "") + end
+ (show_gpu ? c_color + rjust(gpu_str, 5) + ' ' + end : "");
if (lc++ > height - 5) break;
else if (lc > height - 5 and proc_banner_shown) break;
}
Expand Down Expand Up @@ -2182,6 +2239,14 @@ namespace Proc {
return rng::find(plist, pair.first, &proc_info::pid) == plist.end();
});

std::erase_if(p_graphs_gpu, [&](const auto& pair) {
return rng::find(plist, pair.first, &proc_info::pid) == plist.end();
});

std::erase_if(p_counters_gpu, [&](const auto& pair) {
return rng::find(plist, pair.first, &proc_info::pid) == plist.end();
});

std::erase_if(p_wide_cmd, [&](const auto& pair) {
return rng::find(plist, pair.first, &proc_info::pid) == plist.end();
});
Expand Down Expand Up @@ -2230,7 +2295,9 @@ namespace Draw {
Runner::redraw = true;
if (not (Proc::resized or Global::resized)) {
Proc::p_counters.clear();
Proc::p_counters_gpu.clear();
Proc::p_graphs.clear();
Proc::p_graphs_gpu.clear();
}
if (Menu::active) Menu::redraw = true;

Expand Down
5 changes: 5 additions & 0 deletions src/btop_input.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -377,6 +377,11 @@ namespace Input {
else if (key == "c")
Config::flip("proc_per_core");

else if (key == "g") {
Config::flip("proc_gpu_only");
Config::set("update_following", true);
}

else if (key == "%")
Config::flip("proc_mem_bytes");

Expand Down
14 changes: 13 additions & 1 deletion src/btop_menu.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -201,6 +201,7 @@ namespace Menu {
{"f, /", "To enter a process filter. Start with ! for regex."},
{"F", "Follow selected process."},
{"u", "Pause process list."},
{"g", "Toggle GPU-only process filter."},
{"delete", "Clear any entered filter."},
{"c", "Toggle per-core cpu usage of processes."},
{"r", "Reverse sorting order in processes box."},
Expand Down Expand Up @@ -817,7 +818,8 @@ namespace Menu {
"",
"Possible values:",
"\"pid\", \"program\", \"arguments\", \"threads\",",
"\"user\", \"memory\", \"cpu lazy\" and",
"\"user\", \"memory\", \"gpu\",",
"\"gpu memory\", \"cpu lazy\" and",
"\"cpu direct\".",
"",
"\"cpu lazy\" updates top process over time.",
Expand Down Expand Up @@ -872,6 +874,16 @@ namespace Menu {
"Show cpu graph for each process.",
"",
"True or False"},
{"proc_gpu_graphs",
"Show gpu graph for each process.",
"",
"True or False"},
{"proc_gpu_only",
"Show only GPU-active processes.",
"",
"When enabled, only processes with",
"non-zero GPU usage or GPU memory",
"allocation are shown."},
{"proc_filter_kernel",
"(Linux) Filter kernel processes from output.",
"",
Expand Down
32 changes: 24 additions & 8 deletions src/btop_shared.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -109,8 +109,10 @@ bool set_priority(pid_t pid, int priority) {
case 3: rng::stable_sort(proc_vec, rng::less{}, &proc_info::threads); break;
case 4: rng::stable_sort(proc_vec, rng::greater{}, &proc_info::user); break;
case 5: rng::stable_sort(proc_vec, rng::less{}, &proc_info::mem); break;
case 6: rng::stable_sort(proc_vec, rng::less{}, &proc_info::cpu_p); break;
case 7: rng::stable_sort(proc_vec, rng::less{}, &proc_info::cpu_c); break;
case 6: rng::stable_sort(proc_vec, rng::less{}, &proc_info::gpu_p); break;
case 7: rng::stable_sort(proc_vec, rng::less{}, &proc_info::gpu_m); break;
case 8: rng::stable_sort(proc_vec, rng::less{}, &proc_info::cpu_p); break;
case 9: rng::stable_sort(proc_vec, rng::less{}, &proc_info::cpu_c); break;
}
}
else {
Expand All @@ -121,8 +123,10 @@ bool set_priority(pid_t pid, int priority) {
case 3: rng::stable_sort(proc_vec, rng::greater{}, &proc_info::threads); break;
case 4: rng::stable_sort(proc_vec, rng::less{}, &proc_info::user); break;
case 5: rng::stable_sort(proc_vec, rng::greater{}, &proc_info::mem); break;
case 6: rng::stable_sort(proc_vec, rng::greater{}, &proc_info::cpu_p); break;
case 7: rng::stable_sort(proc_vec, rng::greater{}, &proc_info::cpu_c); break;
case 6: rng::stable_sort(proc_vec, rng::greater{}, &proc_info::gpu_p); break;
case 7: rng::stable_sort(proc_vec, rng::greater{}, &proc_info::gpu_m); break;
case 8: rng::stable_sort(proc_vec, rng::greater{}, &proc_info::cpu_p); break;
case 9: rng::stable_sort(proc_vec, rng::greater{}, &proc_info::cpu_c); break;
}
}

Expand Down Expand Up @@ -150,16 +154,20 @@ bool set_priority(pid_t pid, int priority) {
switch (v_index(sort_vector, sorting)) {
case 3: rng::stable_sort(proc_vec, [](const auto& a, const auto& b) { return a.entry.get().threads < b.entry.get().threads; }); break;
case 5: rng::stable_sort(proc_vec, [](const auto& a, const auto& b) { return a.entry.get().mem < b.entry.get().mem; }); break;
case 6: rng::stable_sort(proc_vec, [](const auto& a, const auto& b) { return a.entry.get().cpu_p < b.entry.get().cpu_p; }); break;
case 7: rng::stable_sort(proc_vec, [](const auto& a, const auto& b) { return a.entry.get().cpu_c < b.entry.get().cpu_c; }); break;
case 6: rng::stable_sort(proc_vec, [](const auto& a, const auto& b) { return a.entry.get().gpu_p < b.entry.get().gpu_p; }); break;
case 7: rng::stable_sort(proc_vec, [](const auto& a, const auto& b) { return a.entry.get().gpu_m < b.entry.get().gpu_m; }); break;
case 8: rng::stable_sort(proc_vec, [](const auto& a, const auto& b) { return a.entry.get().cpu_p < b.entry.get().cpu_p; }); break;
case 9: rng::stable_sort(proc_vec, [](const auto& a, const auto& b) { return a.entry.get().cpu_c < b.entry.get().cpu_c; }); break;
}
}
else {
switch (v_index(sort_vector, sorting)) {
case 3: rng::stable_sort(proc_vec, [](const auto& a, const auto& b) { return a.entry.get().threads > b.entry.get().threads; }); break;
case 5: rng::stable_sort(proc_vec, [](const auto& a, const auto& b) { return a.entry.get().mem > b.entry.get().mem; }); break;
case 6: rng::stable_sort(proc_vec, [](const auto& a, const auto& b) { return a.entry.get().cpu_p > b.entry.get().cpu_p; }); break;
case 7: rng::stable_sort(proc_vec, [](const auto& a, const auto& b) { return a.entry.get().cpu_c > b.entry.get().cpu_c; }); break;
case 6: rng::stable_sort(proc_vec, [](const auto& a, const auto& b) { return a.entry.get().gpu_p > b.entry.get().gpu_p; }); break;
case 7: rng::stable_sort(proc_vec, [](const auto& a, const auto& b) { return a.entry.get().gpu_m > b.entry.get().gpu_m; }); break;
case 8: rng::stable_sort(proc_vec, [](const auto& a, const auto& b) { return a.entry.get().cpu_p > b.entry.get().cpu_p; }); break;
case 9: rng::stable_sort(proc_vec, [](const auto& a, const auto& b) { return a.entry.get().cpu_c > b.entry.get().cpu_c; }); break;
}
}
}
Expand All @@ -173,6 +181,10 @@ bool set_priority(pid_t pid, int priority) {
}

auto matches_filter(const proc_info& proc, const std::string& filter) -> bool {
if (Config::getB("proc_gpu_only") and proc.gpu_p <= 0.0 and proc.gpu_m == 0) {
return false;
}

if (filter.starts_with("!")) {
if (filter.size() == 1) {
return true;
Expand Down Expand Up @@ -242,6 +254,8 @@ bool set_priority(pid_t pid, int priority) {
if (p.state != 'X') {
cur_proc.cpu_p += p.cpu_p;
cur_proc.cpu_c += p.cpu_c;
cur_proc.gpu_p += p.gpu_p;
cur_proc.gpu_m += p.gpu_m;
cur_proc.mem += p.mem;
cur_proc.threads += p.threads;
}
Expand All @@ -251,6 +265,8 @@ bool set_priority(pid_t pid, int priority) {
else if (Config::getB("proc_aggregate") and p.state != 'X') {
cur_proc.cpu_p += p.cpu_p;
cur_proc.cpu_c += p.cpu_c;
cur_proc.gpu_p += p.gpu_p;
cur_proc.gpu_m += p.gpu_m;
cur_proc.mem += p.mem;
cur_proc.threads += p.threads;
}
Expand Down
5 changes: 5 additions & 0 deletions src/btop_shared.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -373,6 +373,8 @@ namespace Proc {
"threads",
"user",
"memory",
"gpu",
"gpu memory",
"cpu direct",
"cpu lazy",
};
Expand Down Expand Up @@ -404,11 +406,14 @@ namespace Proc {
uint64_t mem{};
double cpu_p{}; // defaults to = 0.0
double cpu_c{}; // defaults to = 0.0
double gpu_p{}; // defaults to = 0.0
uint64_t gpu_m{};
char state = '0';
int64_t p_nice{};
uint64_t ppid{};
uint64_t cpu_s{};
uint64_t cpu_t{};
uint64_t gpu_t{};
uint64_t death_time{};
string prefix{}; // defaults to ""
size_t depth{};
Expand Down
Loading
Loading