mirror of https://github.com/aristocratos/btop.git
Added threads, memory to processes
This commit is contained in:
parent
621534f5d4
commit
05eb21dfbb
41
btop.cpp
41
btop.cpp
|
@ -25,6 +25,7 @@ tab-size = 4
|
||||||
#include <thread>
|
#include <thread>
|
||||||
#include <future>
|
#include <future>
|
||||||
#include <atomic>
|
#include <atomic>
|
||||||
|
#include <filesystem>
|
||||||
|
|
||||||
#include <unistd.h>
|
#include <unistd.h>
|
||||||
|
|
||||||
|
@ -35,26 +36,20 @@ tab-size = 4
|
||||||
#include <btop_theme.h>
|
#include <btop_theme.h>
|
||||||
|
|
||||||
#if defined(__linux__)
|
#if defined(__linux__)
|
||||||
#define SYSTEM "linux"
|
|
||||||
#include <btop_linux.h>
|
#include <btop_linux.h>
|
||||||
#elif defined(__unix__) || !defined(__APPLE__) && defined(__MACH__)
|
#elif defined(__unix__) || !defined(__APPLE__) && defined(__MACH__)
|
||||||
#include <sys/param.h>
|
#include <sys/param.h>
|
||||||
#if defined(BSD)
|
#if defined(BSD)
|
||||||
#define SYSTEM "bsd"
|
// #include <btop_bsd.h>
|
||||||
#else
|
|
||||||
#define SYSTEM "unknown"
|
|
||||||
#endif
|
#endif
|
||||||
#elif defined(__APPLE__) && defined(__MACH__)
|
#elif defined(__APPLE__) && defined(__MACH__)
|
||||||
#include <TargetConditionals.h>
|
#include <TargetConditionals.h>
|
||||||
#if TARGET_OS_MAC == 1
|
#if TARGET_OS_MAC == 1
|
||||||
#define SYSTEM "osx"
|
// #include <btop_osx.h>
|
||||||
#else
|
|
||||||
#define SYSTEM "unknown"
|
|
||||||
#endif
|
#endif
|
||||||
#else
|
|
||||||
#define SYSTEM "unknown"
|
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
|
namespace fs = std::filesystem;
|
||||||
using namespace std;
|
using namespace std;
|
||||||
|
|
||||||
|
|
||||||
|
@ -99,7 +94,7 @@ class C_Banner {
|
||||||
string banner_str;
|
string banner_str;
|
||||||
|
|
||||||
public:
|
public:
|
||||||
int width;
|
int width = 0;
|
||||||
|
|
||||||
C_Banner(){
|
C_Banner(){
|
||||||
size_t z = 0;
|
size_t z = 0;
|
||||||
|
@ -112,7 +107,7 @@ public:
|
||||||
fg = hex_to_color(line[0]);
|
fg = hex_to_color(line[0]);
|
||||||
bg_i = 120-z*12;
|
bg_i = 120-z*12;
|
||||||
bg = dec_to_color(bg_i, bg_i, bg_i);
|
bg = dec_to_color(bg_i, bg_i, bg_i);
|
||||||
for (unsigned i = 0; i < line[1].size(); i += 3) {
|
for (uint i = 0; i < line[1].size(); i += 3) {
|
||||||
if (line[1][i] == ' '){
|
if (line[1][i] == ' '){
|
||||||
letter = ' ';
|
letter = ' ';
|
||||||
i -= 2;
|
i -= 2;
|
||||||
|
@ -125,7 +120,7 @@ public:
|
||||||
oc = b_color;
|
oc = b_color;
|
||||||
}
|
}
|
||||||
z++;
|
z++;
|
||||||
if (z < Global::Banner_src.size()) out += Mv::l(ulen(line[1])) + Mv::d(1);
|
if (z < Global::Banner_src.size()) out += Mv::l(new_len) + Mv::d(1);
|
||||||
}
|
}
|
||||||
banner_str = out + Mv::r(18 - Global::Version.size()) + Fx::i + dec_to_color(0,0,0, State::truecolor, "bg") + dec_to_color(150, 150, 150) + "v" + Global::Version;
|
banner_str = out + Mv::r(18 - Global::Version.size()) + Fx::i + dec_to_color(0,0,0, State::truecolor, "bg") + dec_to_color(150, 150, 150) + "v" + Global::Version;
|
||||||
}
|
}
|
||||||
|
@ -154,6 +149,15 @@ int main(int argc, char **argv){
|
||||||
cout.setf(std::ios::boolalpha);
|
cout.setf(std::ios::boolalpha);
|
||||||
if (argc > 1) argumentParser(argc, argv);
|
if (argc > 1) argumentParser(argc, argv);
|
||||||
|
|
||||||
|
//? Init for Linux
|
||||||
|
if (Global::SYSTEM == "linux") {
|
||||||
|
Global::proc_path = (fs::is_directory(fs::path("/proc"))) ? fs::path("/proc") : Global::proc_path;
|
||||||
|
if (Global::proc_path.empty()) {
|
||||||
|
cout << "ERROR: Proc filesystem not detected!" << endl;
|
||||||
|
exit(1);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
//? Initialize terminal and set options
|
//? Initialize terminal and set options
|
||||||
C_Term Term;
|
C_Term Term;
|
||||||
if (!Term.initialized) {
|
if (!Term.initialized) {
|
||||||
|
@ -174,7 +178,6 @@ int main(int argc, char **argv){
|
||||||
//? Initialize the Input class
|
//? Initialize the Input class
|
||||||
C_Input Input;
|
C_Input Input;
|
||||||
|
|
||||||
|
|
||||||
//* ------------------------------------------------ TESTING ------------------------------------------------------
|
//* ------------------------------------------------ TESTING ------------------------------------------------------
|
||||||
|
|
||||||
int debug = 2;
|
int debug = 2;
|
||||||
|
@ -192,6 +195,7 @@ int main(int argc, char **argv){
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
//* Test MENUS
|
//* Test MENUS
|
||||||
// for (auto& outer : Global::Menus){
|
// for (auto& outer : Global::Menus){
|
||||||
// for (auto& inner : outer.second){
|
// for (auto& inner : outer.second){
|
||||||
|
@ -264,10 +268,10 @@ int main(int argc, char **argv){
|
||||||
// insert Processes call here
|
// insert Processes call here
|
||||||
|
|
||||||
|
|
||||||
|
uint lc;
|
||||||
unsigned lc;
|
|
||||||
string ostring;
|
string ostring;
|
||||||
cout << rjustify("Pid:", 8) << " " << ljustify("Program:", 16) << " " << ljustify("Command:", Term.width - 48) << " " << rjustify("User:", 10) << " " << rjustify("Cpu%", 4) << "\n" << Mv::save << flush;
|
cout << rjustify("Pid:", 8) << " " << ljustify("Program:", 16) << " " << ljustify("Command:", Term.width - 69) << " Threads: " <<
|
||||||
|
ljustify("User:", 10) << " " << rjustify("MemB", 5) << " " << rjustify("Cpu%", 14) << "\n" << Mv::save << flush;
|
||||||
|
|
||||||
while (Input() != "q") {
|
while (Input() != "q") {
|
||||||
timestamp = time_ms();
|
timestamp = time_ms();
|
||||||
|
@ -275,9 +279,10 @@ int main(int argc, char **argv){
|
||||||
timestamp = time_ms() - timestamp;
|
timestamp = time_ms() - timestamp;
|
||||||
ostring.clear();
|
ostring.clear();
|
||||||
lc = 0;
|
lc = 0;
|
||||||
for (auto& [lpid, lname, lcmd, luser, lcpu, lcpu_s] : plist){
|
for (auto& [lpid, lname, lcmd, lthread, luser, lmem, lcpu, lcpu_s] : plist){
|
||||||
(void) lcpu_s;
|
(void) lcpu_s;
|
||||||
ostring += rjustify(to_string(lpid), 8) + " " + ljustify(lname, 16) + " " + ljustify(lcmd, Term.width - 48, true) + " " + rjustify(luser, 10) + " ";
|
ostring += rjustify(to_string(lpid), 8) + " " + ljustify(lname, 16) + " " + ljustify(lcmd, Term.width - 66, true) + " " +
|
||||||
|
rjustify(to_string(lthread), 5) + " " + ljustify(luser, 10) + " " + rjustify(floating_humanizer(lmem, true, 1), 5) + string(11, ' ');
|
||||||
ostring += (lcpu > 100) ? rjustify(to_string(lcpu), 3) + " " : rjustify(to_string(lcpu), 4);
|
ostring += (lcpu > 100) ? rjustify(to_string(lcpu), 3) + " " : rjustify(to_string(lcpu), 4);
|
||||||
ostring += "\n";
|
ostring += "\n";
|
||||||
if (lc++ > Term.height - 20) break;
|
if (lc++ > Term.height - 20) break;
|
||||||
|
|
|
@ -39,7 +39,7 @@ using namespace std;
|
||||||
namespace State {
|
namespace State {
|
||||||
bool truecolor = true;
|
bool truecolor = true;
|
||||||
string fg, bg;
|
string fg, bg;
|
||||||
unsigned width, height;
|
uint width, height;
|
||||||
}
|
}
|
||||||
|
|
||||||
class C_Config {
|
class C_Config {
|
||||||
|
|
|
@ -113,6 +113,11 @@ namespace Global {
|
||||||
} }
|
} }
|
||||||
} }
|
} }
|
||||||
};
|
};
|
||||||
|
|
||||||
|
//? Units for floating_humanizer function
|
||||||
|
const vector<string> Units_bit = {"bit", "Kib", "Mib", "Gib", "Tib", "Pib", "Eib", "Zib", "Yib", "Bib", "GEb"};
|
||||||
|
const vector<string> Units_byte = {"Byte", "KiB", "MiB", "GiB", "TiB", "PiB", "EiB", "ZiB", "YiB", "BiB", "GEB"};
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
#endif
|
#endif
|
||||||
|
|
165
src/btop_linux.h
165
src/btop_linux.h
|
@ -37,23 +37,34 @@ tab-size = 4
|
||||||
namespace fs = std::filesystem;
|
namespace fs = std::filesystem;
|
||||||
using namespace std;
|
using namespace std;
|
||||||
|
|
||||||
|
namespace Global {
|
||||||
|
|
||||||
|
const string SYSTEM = "linux";
|
||||||
|
filesystem::path proc_path;
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
class Processes {
|
class Processes {
|
||||||
uint64_t tstamp;
|
uint64_t tstamp;
|
||||||
long int clk_tck;
|
long int clk_tck;
|
||||||
map<int, tuple<string, string, string>> cache;
|
map<int, tuple<string, string, string>> cache;
|
||||||
map<string, unsigned> sorts = {
|
map<string, uint> sorts = {
|
||||||
{"pid", 0},
|
{"pid", 0},
|
||||||
{"name", 1},
|
{"name", 1},
|
||||||
{"command", 2},
|
{"command", 2},
|
||||||
{"user", 3},
|
{"threads", 3},
|
||||||
{"cpu direct", 4},
|
{"user", 4},
|
||||||
{"cpu lazy", 5}
|
{"memory", 5},
|
||||||
|
{"cpu direct", 6},
|
||||||
|
{"cpu lazy", 7}
|
||||||
};
|
};
|
||||||
map<string, string> uid_user;
|
map<string, string> uid_user;
|
||||||
|
fs::path passwd_path;
|
||||||
fs::file_time_type passwd_time;
|
fs::file_time_type passwd_time;
|
||||||
map<int, uint64_t> cpu_times;
|
map<int, uint64_t> cpu_times;
|
||||||
map<int, uint64_t> cpu_second;
|
map<int, uint64_t> cpu_second;
|
||||||
unsigned counter = 0;
|
uint counter = 0;
|
||||||
|
long page_size = sysconf(_SC_PAGE_SIZE);
|
||||||
public:
|
public:
|
||||||
atomic<bool> stop;
|
atomic<bool> stop;
|
||||||
atomic<bool> running;
|
atomic<bool> running;
|
||||||
|
@ -62,40 +73,42 @@ public:
|
||||||
auto collect(string sorting="pid", bool reverse=false, string filter=""){
|
auto collect(string sorting="pid", bool reverse=false, string filter=""){
|
||||||
running.store(true);
|
running.store(true);
|
||||||
int pid;
|
int pid;
|
||||||
uint64_t cpu_t;
|
uint64_t cpu_t, rss_mem;
|
||||||
double cpu, cpu_s;
|
double cpu, cpu_s;
|
||||||
|
size_t threads;
|
||||||
ifstream pread;
|
ifstream pread;
|
||||||
string pid_str, name, cmd, attr, user, instr, uid, status, tmpstr;
|
string pid_str, name, cmd, attr, user, instr, uid, status, tmpstr, smap;
|
||||||
auto since_last = time_ms() - tstamp;
|
auto since_last = time_ms() - tstamp;
|
||||||
if (since_last < 1) since_last = 1;
|
if (since_last < 1) since_last = 1;
|
||||||
auto uptime = system_uptime();
|
auto uptime = system_uptime();
|
||||||
auto sortint = (sorts.contains(sorting)) ? sorts[sorting] : 5;
|
auto sortint = (sorts.contains(sorting)) ? sorts[sorting] : 5;
|
||||||
vector<string> pstat;
|
vector<string> pstat;
|
||||||
|
|
||||||
//? Return type! Values in tuple: pid, program, command, username, cpu%, cpu cumulative
|
//? Return type! Values in tuple: pid, program, command, threads, username, mem KiB, cpu%, cpu cumulative
|
||||||
vector<tuple<int, string, string, string, double, double>> procs;
|
vector<tuple<int, string, string, size_t, string, uint64_t, double, double>> procs;
|
||||||
|
|
||||||
//* Update uid_user map if /etc/passwd changed since last run
|
//* Update uid_user map if /etc/passwd changed since last run
|
||||||
if (fs::last_write_time(fs::path("/etc/passwd")) != passwd_time) {
|
if (!passwd_path.empty() && fs::last_write_time(passwd_path) != passwd_time) {
|
||||||
string r_uid, r_user;
|
string r_uid, r_user;
|
||||||
passwd_time = fs::last_write_time(fs::path("/etc/passwd"));
|
passwd_time = fs::last_write_time(passwd_path);
|
||||||
uid_user.clear();
|
uid_user.clear();
|
||||||
pread.clear();
|
ifstream pread(passwd_path);
|
||||||
ifstream pread("/etc/passwd");
|
if (pread.good()) {
|
||||||
while (true){
|
while (true){
|
||||||
getline(pread, r_user, ':');
|
getline(pread, r_user, ':');
|
||||||
pread.ignore(numeric_limits<streamsize>::max(), ':');
|
pread.ignore(numeric_limits<streamsize>::max(), ':');
|
||||||
getline(pread, r_uid, ':');
|
getline(pread, r_uid, ':');
|
||||||
uid_user[r_uid] = r_user;
|
uid_user[r_uid] = r_user;
|
||||||
pread.ignore(numeric_limits<streamsize>::max(), '\n');
|
pread.ignore(numeric_limits<streamsize>::max(), '\n');
|
||||||
if (pread.eof()) break;
|
if (pread.eof()) break;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
pread.close();
|
pread.close();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
//* Iterate over all pid directories in /proc and get relevant values
|
//* Iterate over all pid directories in /proc and get relevant values
|
||||||
for (auto& d: fs::directory_iterator("/proc")){
|
for (auto& d: fs::directory_iterator(Global::proc_path)){
|
||||||
if (stop.load()) {
|
if (stop.load()) {
|
||||||
procs.clear();
|
procs.clear();
|
||||||
running.store(false);
|
running.store(false);
|
||||||
|
@ -104,16 +117,22 @@ public:
|
||||||
}
|
}
|
||||||
pid_str = fs::path(d.path()).filename();
|
pid_str = fs::path(d.path()).filename();
|
||||||
cpu = 0.0;
|
cpu = 0.0;
|
||||||
|
rss_mem = 0;
|
||||||
if (d.is_directory() && isdigit(pid_str[0])) {
|
if (d.is_directory() && isdigit(pid_str[0])) {
|
||||||
pid = stoi(pid_str);
|
pid = stoi(pid_str);
|
||||||
|
|
||||||
//* Get cpu usage
|
//* Get cpu usage, threads and rss mem from [pid]/stat
|
||||||
if (fs::is_regular_file((string)d.path() + "/stat")) {
|
if (fs::exists((string)d.path() + "/stat")) {
|
||||||
pstat.clear();
|
pread.clear(); pstat.clear();
|
||||||
ifstream pread((string)d.path() + "/stat");
|
ifstream pread((string)d.path() + "/stat");
|
||||||
while (getline(pread, instr, ' ')) pstat.push_back(instr);
|
if (pread.good()) while (getline(pread, instr, ' ')) pstat.push_back(instr);
|
||||||
pread.close();
|
pread.close();
|
||||||
|
|
||||||
|
if (pstat.size() < 37) continue;
|
||||||
|
|
||||||
|
//? Process number of threads
|
||||||
|
threads = stoul(pstat[19]);
|
||||||
|
|
||||||
//? Process utime + stime
|
//? Process utime + stime
|
||||||
cpu_t = stoull(pstat[13]) + stoull(pstat[14]);
|
cpu_t = stoull(pstat[13]) + stoull(pstat[14]);
|
||||||
if (!cpu_times.contains(pid)) cpu_times[pid] = cpu_t;
|
if (!cpu_times.contains(pid)) cpu_times[pid] = cpu_t;
|
||||||
|
@ -121,6 +140,9 @@ public:
|
||||||
//? Cache process start time
|
//? Cache process start time
|
||||||
if (!cpu_second.contains(pid)) cpu_second[pid] = stoull(pstat[21]);
|
if (!cpu_second.contains(pid)) cpu_second[pid] = stoull(pstat[21]);
|
||||||
|
|
||||||
|
//? Get RSS memory in KiB (will be overriden by /status if available)
|
||||||
|
rss_mem = (stoull(pstat[23]) * page_size) >> 10;
|
||||||
|
|
||||||
//? Process cpu usage since last update, 100'000 because (100 percent * 1000 milliseconds) for correct conversion
|
//? Process cpu usage since last update, 100'000 because (100 percent * 1000 milliseconds) for correct conversion
|
||||||
cpu = static_cast<double>(100000 * (cpu_t - cpu_times[pid]) / since_last) / clk_tck;
|
cpu = static_cast<double>(100000 * (cpu_t - cpu_times[pid]) / since_last) / clk_tck;
|
||||||
|
|
||||||
|
@ -129,86 +151,106 @@ public:
|
||||||
cpu_times[pid] = cpu_t;
|
cpu_times[pid] = cpu_t;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
//* Get RSS memory in KiB
|
||||||
|
if (fs::exists((string)d.path() + "/status")) {
|
||||||
|
pread.clear(); status.clear(); tmpstr.clear();
|
||||||
|
ifstream pread((string)d.path() + "/status");
|
||||||
|
if (pread.good()) {
|
||||||
|
while (getline(pread, status, ':')){
|
||||||
|
if (status == "VmRSS") {
|
||||||
|
pread.ignore();
|
||||||
|
pread >> ws;
|
||||||
|
getline(pread, tmpstr, 'k');
|
||||||
|
tmpstr.pop_back();
|
||||||
|
break;
|
||||||
|
} else pread.ignore(numeric_limits<streamsize>::max(), '\n');
|
||||||
|
}
|
||||||
|
}
|
||||||
|
pread.close();
|
||||||
|
if (!tmpstr.empty()) rss_mem = stoull(tmpstr);
|
||||||
|
}
|
||||||
|
|
||||||
//* Cache program name, command and username
|
//* Cache program name, command and username
|
||||||
if (!cache.contains(pid)) {
|
if (!cache.contains(pid)) {
|
||||||
if (fs::is_regular_file((string)d.path() + "/comm")) {
|
if (fs::exists((string)d.path() + "/comm")) {
|
||||||
|
pread.clear(); name.clear();
|
||||||
ifstream pread((string)d.path() + "/comm");
|
ifstream pread((string)d.path() + "/comm");
|
||||||
getline(pread, name);
|
if (pread.good()) getline(pread, name);
|
||||||
pread.close();
|
pread.close();
|
||||||
}
|
}
|
||||||
if (fs::is_regular_file((string)d.path() + "/cmdline")) {
|
if (fs::exists((string)d.path() + "/cmdline")) {
|
||||||
cmd.clear();
|
pread.clear(); cmd.clear(); tmpstr.clear();
|
||||||
ifstream pread((string)d.path() + "/cmdline");
|
ifstream pread((string)d.path() + "/cmdline");
|
||||||
while(getline(pread, tmpstr, '\0')) cmd += tmpstr + " ";
|
if (pread.good()) while(getline(pread, tmpstr, '\0')) cmd += tmpstr + " ";
|
||||||
pread.close();
|
pread.close();
|
||||||
if (!cmd.empty()) cmd.pop_back();
|
if (!cmd.empty()) cmd.pop_back();
|
||||||
}
|
}
|
||||||
if (fs::exists((string)d.path() + "/status")) {
|
if (fs::exists((string)d.path() + "/status")) {
|
||||||
|
pread.clear(); status.clear(); uid.clear();
|
||||||
ifstream pread((string)d.path() + "/status");
|
ifstream pread((string)d.path() + "/status");
|
||||||
status.clear();
|
if (pread.good()) {
|
||||||
while (!pread.eof()){
|
while (!pread.eof()){
|
||||||
getline(pread, status, ':');
|
getline(pread, status, ':');
|
||||||
if (status == "Uid") {
|
if (status == "Uid") {
|
||||||
pread.ignore();
|
pread.ignore();
|
||||||
getline(pread, uid, '\t');
|
getline(pread, uid, '\t');
|
||||||
break;
|
break;
|
||||||
} else {
|
} else {
|
||||||
pread.ignore(numeric_limits<streamsize>::max(), '\n');
|
pread.ignore(numeric_limits<streamsize>::max(), '\n');
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
pread.close();
|
pread.close();
|
||||||
user = (uid_user.contains(uid)) ? uid_user.at(uid) : "";
|
user = (!uid.empty() && uid_user.contains(uid)) ? uid_user.at(uid) : uid;
|
||||||
}
|
}
|
||||||
cache[pid] = make_tuple(name, cmd, user);
|
cache[pid] = make_tuple(name, cmd, user);
|
||||||
}
|
}
|
||||||
|
|
||||||
// //* Match filter if applicable
|
// //* Match filter if applicable
|
||||||
if (!filter.empty() &&
|
if (!filter.empty() &&
|
||||||
pid_str.find(filter) == string::npos &&
|
pid_str.find(filter) == string::npos && //? Pid
|
||||||
get<0>(cache[pid]).find(filter) == string::npos &&
|
get<0>(cache[pid]).find(filter) == string::npos && //? Program
|
||||||
get<1>(cache[pid]).find(filter) == string::npos &&
|
get<1>(cache[pid]).find(filter) == string::npos && //? Command
|
||||||
get<2>(cache[pid]).find(filter) == string::npos
|
get<2>(cache[pid]).find(filter) == string::npos //? User
|
||||||
) continue;
|
) continue;
|
||||||
|
|
||||||
//* Create tuple
|
//* Create tuple
|
||||||
procs.push_back(make_tuple(pid, get<0>(cache[pid]), get<1>(cache[pid]), get<2>(cache[pid]), cpu, cpu_s));
|
procs.push_back(make_tuple(pid, get<0>(cache[pid]), get<1>(cache[pid]), threads, get<2>(cache[pid]), rss_mem, cpu, cpu_s));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// auto st = time_ms();
|
// auto st = time_ms();
|
||||||
|
|
||||||
//* Sort processes vector
|
//* Sort processes vector
|
||||||
ranges::sort(procs, [&sortint, &reverse](tuple<int, string, string, string, double, double>& a, tuple<int, string, string, string, double, double>& b) {
|
ranges::sort(procs, [&sortint, &reverse]( tuple<int, string, string, size_t, string, uint64_t, double, double>& a,
|
||||||
|
tuple<int, string, string, size_t, string, uint64_t, double, double>& b)
|
||||||
|
{
|
||||||
switch (sortint) {
|
switch (sortint) {
|
||||||
case 0: return (reverse) ? get<0>(a) < get<0>(b) : get<0>(a) > get<0>(b); //? Pid
|
case 0: return (reverse) ? get<0>(a) < get<0>(b) : get<0>(a) > get<0>(b); //? Pid
|
||||||
case 1: return (reverse) ? get<1>(a) < get<1>(b) : get<1>(a) > get<1>(b); //? Program
|
case 1: return (reverse) ? get<1>(a) < get<1>(b) : get<1>(a) > get<1>(b); //? Program
|
||||||
case 2: return (reverse) ? get<2>(a) < get<2>(b) : get<2>(a) > get<2>(b); //? Command
|
case 2: return (reverse) ? get<2>(a) < get<2>(b) : get<2>(a) > get<2>(b); //? Command
|
||||||
case 3: return (reverse) ? get<3>(a) < get<3>(b) : get<3>(a) > get<3>(b); //? User
|
case 3: return (reverse) ? get<3>(a) < get<3>(b) : get<3>(a) > get<3>(b); //? Threads
|
||||||
case 4: return (reverse) ? get<4>(a) < get<4>(b) : get<4>(a) > get<4>(b); //? Cpu direct
|
case 4: return (reverse) ? get<4>(a) < get<4>(b) : get<4>(a) > get<4>(b); //? User
|
||||||
case 5: return (reverse) ? get<5>(a) < get<5>(b) : get<5>(a) > get<5>(b); //? Cpu lazy
|
case 5: return (reverse) ? get<5>(a) < get<5>(b) : get<5>(a) > get<5>(b); //? Memory
|
||||||
|
case 6: return (reverse) ? get<6>(a) < get<6>(b) : get<6>(a) > get<6>(b); //? Cpu direct
|
||||||
|
case 7: return (reverse) ? get<7>(a) < get<7>(b) : get<7>(a) > get<7>(b); //? Cpu lazy
|
||||||
}
|
}
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
);
|
);
|
||||||
|
|
||||||
//* 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 == 5 && !reverse) {
|
if (sortint == 6 && !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 && get<4>(procs[i]) > max) max = get<4>(procs[i]);
|
if (i <= 5 && get<6>(procs[i]) > max) max = get<6>(procs[i]);
|
||||||
else if (i == 6) target = (max > 30.0) ? max : 10.0;
|
else if (i == 6) target = (max > 30.0) ? max : 10.0;
|
||||||
if (i == offset && get<4>(procs[i]) > 30.0) offset++;
|
if (i == offset && get<6>(procs[i]) > 30.0) offset++;
|
||||||
else if (get<4>(procs[i]) > target) rotate(procs.begin() + offset, procs.begin() + i, procs.begin() + i + 1);
|
else if (get<6>(procs[i]) > target) rotate(procs.begin() + offset, procs.begin() + i, procs.begin() + i + 1);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
//* Clear all cached values at a regular interval to get rid of dead processes
|
||||||
|
|
||||||
// cout << "Sort took: " << time_ms() - st << "ms " << flush;
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
//* Clear all cached values at a regular interval
|
|
||||||
if (++counter >= 10000 || (filter.empty() && cache.size() > procs.size() + 100)) {
|
if (++counter >= 10000 || (filter.empty() && cache.size() > procs.size() + 100)) {
|
||||||
counter = 0;
|
counter = 0;
|
||||||
cache.clear();
|
cache.clear();
|
||||||
|
@ -225,6 +267,7 @@ public:
|
||||||
clk_tck = sysconf(_SC_CLK_TCK);
|
clk_tck = sysconf(_SC_CLK_TCK);
|
||||||
tstamp = time_ms();
|
tstamp = time_ms();
|
||||||
stop.store(false);
|
stop.store(false);
|
||||||
|
passwd_path = (fs::exists(fs::path("/etc/passwd"))) ? fs::path("/etc/passwd") : passwd_path;
|
||||||
collect();
|
collect();
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
|
@ -33,7 +33,7 @@ using namespace std;
|
||||||
//? --------------------------------------------------- FUNCTIONS -----------------------------------------------------
|
//? --------------------------------------------------- FUNCTIONS -----------------------------------------------------
|
||||||
|
|
||||||
//* Convert 24-bit colors to 256 colors using 6x6x6 color cube
|
//* Convert 24-bit colors to 256 colors using 6x6x6 color cube
|
||||||
int truecolor_to_256(unsigned r, unsigned g, unsigned b){
|
int truecolor_to_256(uint r, uint g, uint b){
|
||||||
if (r / 11 == g / 11 && g / 11 == b / 11) {
|
if (r / 11 == g / 11 && g / 11 == b / 11) {
|
||||||
return 232 + r / 11;
|
return 232 + r / 11;
|
||||||
} else {
|
} else {
|
||||||
|
@ -54,7 +54,7 @@ string hex_to_color(string hexa, bool t_to_256=false, string depth="fg"){
|
||||||
pre += (t_to_256) ? "5;" : "2;";
|
pre += (t_to_256) ? "5;" : "2;";
|
||||||
|
|
||||||
if (hexa.size() == 2){
|
if (hexa.size() == 2){
|
||||||
unsigned h_int = stoi(hexa, 0, 16);
|
uint h_int = stoi(hexa, 0, 16);
|
||||||
if (t_to_256){
|
if (t_to_256){
|
||||||
return pre + to_string(truecolor_to_256(h_int, h_int, h_int)) + "m";
|
return pre + to_string(truecolor_to_256(h_int, h_int, h_int)) + "m";
|
||||||
} else {
|
} else {
|
||||||
|
@ -83,7 +83,7 @@ string hex_to_color(string hexa, bool t_to_256=false, string depth="fg"){
|
||||||
//* Args r: [0-255], g: [0-255], b: [0-255]
|
//* Args r: [0-255], g: [0-255], b: [0-255]
|
||||||
//* t_to_256: [true|false] convert 24bit value to 256 color value
|
//* t_to_256: [true|false] convert 24bit value to 256 color value
|
||||||
//* depth: ["fg"|"bg"] for either a foreground color or a background color
|
//* depth: ["fg"|"bg"] for either a foreground color or a background color
|
||||||
string dec_to_color(unsigned r, unsigned g, unsigned b, bool t_to_256=false, string depth="fg"){
|
string dec_to_color(uint r, uint g, uint b, bool t_to_256=false, string depth="fg"){
|
||||||
depth = (depth == "fg") ? "38" : "48";
|
depth = (depth == "fg") ? "38" : "48";
|
||||||
string pre = Fx::e + depth + ";";
|
string pre = Fx::e + depth + ";";
|
||||||
pre += (t_to_256) ? "5;" : "2;";
|
pre += (t_to_256) ? "5;" : "2;";
|
||||||
|
|
|
@ -42,7 +42,7 @@ using namespace std;
|
||||||
//* Collection of escape codes for text style and formatting
|
//* Collection of escape codes for text style and formatting
|
||||||
namespace Fx {
|
namespace Fx {
|
||||||
//* Escape sequence start
|
//* Escape sequence start
|
||||||
const string e = "\x1b[";
|
const string e = "\033[";
|
||||||
|
|
||||||
//* Bold on
|
//* Bold on
|
||||||
const string b = e + "1m";
|
const string b = e + "1m";
|
||||||
|
@ -96,9 +96,9 @@ namespace Mv {
|
||||||
//? --------------------------------------------------- FUNCTIONS -----------------------------------------------------
|
//? --------------------------------------------------- FUNCTIONS -----------------------------------------------------
|
||||||
|
|
||||||
//* Return number of UTF8 characters in a string
|
//* Return number of UTF8 characters in a string
|
||||||
size_t ulen(string s){
|
inline size_t ulen(string s){
|
||||||
return std::count_if(s.begin(), s.end(),
|
return std::count_if(s.begin(), s.end(),
|
||||||
[](char c) { return (static_cast<unsigned char>(c) & 0xC0) != 0x80; } );
|
[](char& c) { return (c & 0xC0) != 0x80; } );
|
||||||
}
|
}
|
||||||
|
|
||||||
//* Return current time since epoch in milliseconds
|
//* Return current time since epoch in milliseconds
|
||||||
|
@ -152,7 +152,7 @@ vector<string> ssplit(string str, string delim = " ", int times = 0){
|
||||||
}
|
}
|
||||||
|
|
||||||
//* Put current thread to sleep for <ms> milliseconds
|
//* Put current thread to sleep for <ms> milliseconds
|
||||||
void sleep_ms(unsigned ms) {
|
void sleep_ms(uint ms) {
|
||||||
std::this_thread::sleep_for(std::chrono::milliseconds(ms));
|
std::this_thread::sleep_for(std::chrono::milliseconds(ms));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -207,9 +207,9 @@ string trans(string str){
|
||||||
return (newstr.empty()) ? str : newstr;
|
return (newstr.empty()) ? str : newstr;
|
||||||
}
|
}
|
||||||
|
|
||||||
string sec_to_dhms(unsigned sec){
|
string sec_to_dhms(uint sec){
|
||||||
string out;
|
string out;
|
||||||
unsigned d, h, m;
|
uint d, h, m;
|
||||||
d = sec / (3600 * 24);
|
d = sec / (3600 * 24);
|
||||||
sec %= 3600 * 24;
|
sec %= 3600 * 24;
|
||||||
h = sec / 3600;
|
h = sec / 3600;
|
||||||
|
@ -231,6 +231,41 @@ double system_uptime(){
|
||||||
return stod(upstr);
|
return stod(upstr);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
//* Scales up in steps of 1024 to highest possible unit and returns string with unit suffixed
|
||||||
|
//* bit=True or defaults to bytes
|
||||||
|
//* start=int to set 1024 multiplier starting unit
|
||||||
|
//* short=True always returns 0 decimals and shortens unit to 1 character
|
||||||
|
string floating_humanizer(uint64_t value, bool shorten=false, uint start=0, bool bit=false, bool per_second=false){
|
||||||
|
string out;
|
||||||
|
uint mult = (bit) ? 8 : 1;
|
||||||
|
auto& units = (bit) ? Global::Units_bit : Global::Units_byte;
|
||||||
|
|
||||||
|
value *= 100 * mult;
|
||||||
|
|
||||||
|
while (value >= 102400){
|
||||||
|
value >>= 10;
|
||||||
|
if (value < 100){
|
||||||
|
out = to_string(value);
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
start++;
|
||||||
|
}
|
||||||
|
if (out.empty()) {
|
||||||
|
out = to_string(value);
|
||||||
|
if (out.size() == 4 && start > 0) { out.pop_back(); out.insert(2, ".");}
|
||||||
|
else if (out.size() == 3 && start > 0) out.insert(1, ".");
|
||||||
|
else if (out.size() >= 2) out.resize(out.size() - 2);
|
||||||
|
}
|
||||||
|
if (shorten){
|
||||||
|
if (out.find('.') != string::npos) out = to_string((int)round(stof(out)));
|
||||||
|
if (out.size() > 3) { out = to_string((int)(out[0] - '0') + 1); start++;}
|
||||||
|
out.push_back(units[start][0]);
|
||||||
|
}
|
||||||
|
else out += " " + units[start];
|
||||||
|
|
||||||
|
if (per_second) out += (bit) ? "ps" : "/s";
|
||||||
|
return out;
|
||||||
|
}
|
||||||
|
|
||||||
//? --------------------------------------------------- CLASSES -----------------------------------------------------
|
//? --------------------------------------------------- CLASSES -----------------------------------------------------
|
||||||
|
|
||||||
|
@ -240,8 +275,8 @@ class C_Term {
|
||||||
public:
|
public:
|
||||||
bool initialized = false;
|
bool initialized = false;
|
||||||
bool resized = false;
|
bool resized = false;
|
||||||
unsigned width = 0;
|
uint width = 0;
|
||||||
unsigned height = 0;
|
uint height = 0;
|
||||||
|
|
||||||
//* Hide terminal cursor
|
//* Hide terminal cursor
|
||||||
const string hide_cursor = Fx::e + "?25l";
|
const string hide_cursor = Fx::e + "?25l";
|
||||||
|
|
Loading…
Reference in New Issue