From 8f23721f86f9063f2118783b6768337d6a270506 Mon Sep 17 00:00:00 2001 From: Avinash Thakur Date: Sat, 25 Nov 2023 20:58:35 +0530 Subject: [PATCH] add grouped memory & cpu columns --- Action.c | 10 ++++++ Process.c | 51 ++++++++++++++++++++++++++++++ Process.h | 10 ++++++ ProcessTable.c | 6 ++++ Row.c | 2 +- RowField.h | 2 ++ darwin/DarwinProcess.c | 4 ++- dragonflybsd/DragonFlyBSDProcess.c | 2 ++ freebsd/FreeBSDProcess.c | 2 ++ htop.1.in | 9 ++++++ linux/LinuxProcess.c | 2 ++ netbsd/NetBSDProcess.c | 15 +++++++++ openbsd/OpenBSDProcess.c | 15 +++++++++ pcp/PCPProcess.c | 2 ++ solaris/SolarisProcess.c | 2 ++ unsupported/UnsupportedProcess.c | 2 ++ 16 files changed, 134 insertions(+), 2 deletions(-) diff --git a/Action.c b/Action.c index 61cc1ef96..31477fcdf 100644 --- a/Action.c +++ b/Action.c @@ -219,10 +219,18 @@ static Htop_Reaction actionSortByMemory(State* st) { return Action_setSortKey(st->host->settings, PERCENT_MEM); } +static Htop_Reaction actionSortByMemoryGroup(State* st) { + return Action_setSortKey(st->host->settings, PERCENT_MEM_GROUP); +} + static Htop_Reaction actionSortByCPU(State* st) { return Action_setSortKey(st->host->settings, PERCENT_CPU); } +static Htop_Reaction actionSortByCPUGroup(State* st) { + return Action_setSortKey(st->host->settings, PERCENT_CPU_GROUP); +} + static Htop_Reaction actionSortByTime(State* st) { return Action_setSortKey(st->host->settings, TIME); } @@ -897,9 +905,11 @@ void Action_setBindings(Htop_Action* keys) { keys['I'] = actionInvertSortOrder; keys['K'] = actionToggleKernelThreads; keys['M'] = actionSortByMemory; + keys['X'] = actionSortByMemoryGroup; keys['N'] = actionSortByPID; keys['O'] = actionToggleRunningInContainer; keys['P'] = actionSortByCPU; + keys['W'] = actionSortByCPUGroup; keys['S'] = actionSetup; keys['T'] = actionSortByTime; keys['U'] = actionUntagAll; diff --git a/Process.c b/Process.c index a80d1ee83..071be634c 100644 --- a/Process.c +++ b/Process.c @@ -660,12 +660,14 @@ void Process_writeField(const Process* this, RichString* str, RowField field) { xSnprintf(buffer, n, "%4ld ", this->nlwp); break; case PERCENT_CPU: Row_printPercentage(this->percent_cpu, buffer, n, Row_fieldWidths[PERCENT_CPU], &attr); break; + case PERCENT_CPU_GROUP: Row_printPercentage(this->percent_cpu_group, buffer, n, Row_fieldWidths[PERCENT_CPU_GROUP], &attr); break; case PERCENT_NORM_CPU: { float cpuPercentage = this->percent_cpu / host->activeCPUs; Row_printPercentage(cpuPercentage, buffer, n, Row_fieldWidths[PERCENT_CPU], &attr); break; } case PERCENT_MEM: Row_printPercentage(this->percent_mem, buffer, n, 4, &attr); break; + case PERCENT_MEM_GROUP: Row_printPercentage(this->percent_mem_group, buffer, n, 4, &attr); break; case PGRP: xSnprintf(buffer, n, "%*d ", Process_pidDigits, this->pgrp); break; case PID: xSnprintf(buffer, n, "%*d ", Process_pidDigits, Process_getPid(this)); break; case PPID: xSnprintf(buffer, n, "%*d ", Process_pidDigits, Process_getParent(this)); break; @@ -915,8 +917,12 @@ int Process_compareByKey_Base(const Process* p1, const Process* p2, ProcessField case PERCENT_CPU: case PERCENT_NORM_CPU: return compareRealNumbers(p1->percent_cpu, p2->percent_cpu); + case PERCENT_CPU_GROUP: + return compareRealNumbers(p1->percent_cpu_group, p2->percent_cpu_group); case PERCENT_MEM: return SPACESHIP_NUMBER(p1->m_resident, p2->m_resident); + case PERCENT_MEM_GROUP: + return SPACESHIP_NUMBER(p1->percent_mem_group, p2->percent_mem_group); case COMM: return SPACESHIP_NULLSTR(Process_getCommand(p1), Process_getCommand(p2)); case PROC_COMM: { @@ -1073,6 +1079,51 @@ void Process_updateCPUFieldWidths(float percentage) { Row_updateFieldWidth(PERCENT_NORM_CPU, width); } +void Process_updateCPUGroupFieldWidth(float percentage) { + if (percentage < 99.9F) { + Row_updateFieldWidth(PERCENT_CPU_GROUP, 4); + return; + } + + // Add additional two characters, one for "." and another for precision. + uint8_t width = ceil(log10(percentage + 0.1)) + 2; + + Row_updateFieldWidth(PERCENT_CPU_GROUP, width); +} + +void Process_resetGroupFields(pid_t _pid, Process* this, void* _data) { + this->percent_cpu_group = this->percent_cpu; + this->percent_mem_group = this->percent_mem; +} + +void Process_updateGroupFields(pid_t _pid, Process* this, void* _data) { + const Machine* host = this->super.host; + const ProcessTable* pt = (const ProcessTable*) host->processTable; + Process* curProcess = this; + + bool looping = curProcess->percent_cpu_group > 0 || curProcess->percent_mem_group > 0; + + while (looping) { + const pid_t pid = Process_getPid(curProcess); + const pid_t parentPid = Process_getGroupOrParent(curProcess); + if (parentPid == pid) { + looping = false; + + break; + } + Process* parentProc = Hashtable_get(pt->super.table, parentPid); + if (parentProc == NULL) { + // TODO: or assert ? + looping = false; + break; + } + parentProc->percent_cpu_group += this->percent_cpu; + parentProc->percent_mem_group += this->percent_mem; + curProcess = parentProc; + } + Process_updateCPUGroupFieldWidth(curProcess->percent_cpu_group); +} + const ProcessClass Process_class = { .super = { .super = { diff --git a/Process.h b/Process.h index 92908155a..f2dc9b61d 100644 --- a/Process.h +++ b/Process.h @@ -146,9 +146,15 @@ typedef struct Process_ { /* CPU usage during last cycle (in percent) */ float percent_cpu; + /* Sum of percent_mem for self and children */ + float percent_cpu_group; + /* Memory usage during last cycle (in percent) */ float percent_mem; + /* Sum of percent_mem for self and children */ + float percent_mem_group; + /* Scheduling priority */ long int priority; @@ -324,4 +330,8 @@ void Process_writeCommand(const Process* this, int attr, int baseAttr, RichStrin void Process_updateCPUFieldWidths(float percentage); +void Process_resetGroupFields(pid_t _pid, Process* this, void* _data); + +void Process_updateGroupFields(pid_t pid, Process* this, void* _data); + #endif diff --git a/ProcessTable.c b/ProcessTable.c index 39e3eb876..ce136316c 100644 --- a/ProcessTable.c +++ b/ProcessTable.c @@ -55,10 +55,16 @@ static void ProcessTable_prepareEntries(Table* super) { Table_prepareEntries(super); } +static void ProcessTable_aggregate(ProcessTable* this) { + Hashtable_foreach(this->super.table, Process_resetGroupFields, NULL); + Hashtable_foreach(this->super.table, Process_updateGroupFields, NULL); +} + static void ProcessTable_iterateEntries(Table* super) { ProcessTable* this = (ProcessTable*) super; // calling into platform-specific code ProcessTable_goThroughEntries(this); + ProcessTable_aggregate(this); } static void ProcessTable_cleanupEntries(Table* super) { diff --git a/Row.c b/Row.c index f43c82036..f41f16259 100644 --- a/Row.c +++ b/Row.c @@ -153,7 +153,7 @@ static const char* alignedTitleProcessField(ProcessField field, char* titleBuffe } if (Process_fields[field].autoWidth) { - if (field == PERCENT_CPU) + if (field == PERCENT_CPU || field == PERCENT_CPU_GROUP) xSnprintf(titleBuffer, titleBufferSize, "%*s ", Row_fieldWidths[field], title); else xSnprintf(titleBuffer, titleBufferSize, "%-*.*s ", Row_fieldWidths[field], Row_fieldWidths[field], title); diff --git a/RowField.h b/RowField.h index 1e01ea3e9..79a1016d3 100644 --- a/RowField.h +++ b/RowField.h @@ -44,6 +44,8 @@ typedef enum ReservedFields_ { /* Platform specific fields, defined in ${platform}/ProcessField.h */ PLATFORM_PROCESS_FIELDS + PERCENT_CPU_GROUP = 130, + PERCENT_MEM_GROUP = 131, /* Do not add new fields after this entry (dynamic entries follow) */ LAST_RESERVED_FIELD diff --git a/darwin/DarwinProcess.c b/darwin/DarwinProcess.c index 4f58832db..13b66dddb 100644 --- a/darwin/DarwinProcess.c +++ b/darwin/DarwinProcess.c @@ -41,8 +41,10 @@ const ProcessFieldData Process_fields[LAST_PROCESSFIELD] = { [M_RESIDENT] = { .name = "M_RESIDENT", .title = " RES ", .description = "Resident set size, size of the text and data sections, plus stack usage", .flags = 0, .defaultSortDesc = true, }, [ST_UID] = { .name = "ST_UID", .title = "UID", .description = "User ID of the process owner", .flags = 0, }, [PERCENT_CPU] = { .name = "PERCENT_CPU", .title = " CPU%", .description = "Percentage of the CPU time the process used in the last sampling", .flags = 0, .defaultSortDesc = true, .autoWidth = true, }, + [PERCENT_CPU_GROUP] = { .name = "PERCENT_CPU_GROUP", .title = " GCPU%", .description = "Percentage of the CPU time the process and its children used in the last sampling", .flags = 0, .defaultSortDesc = true, .autoWidth = true, }, [PERCENT_NORM_CPU] = { .name = "PERCENT_NORM_CPU", .title = "NCPU%", .description = "Normalized percentage of the CPU time the process used in the last sampling (normalized by cpu count)", .flags = 0, .defaultSortDesc = true, .autoWidth = true, }, - [PERCENT_MEM] = { .name = "PERCENT_MEM", .title = "MEM% ", .description = "Percentage of the memory the process is using, based on resident memory size", .flags = 0, .defaultSortDesc = true, }, + [PERCENT_MEM] = { .name = "PERCENT_MEM", .title = "MEM% ", .description = "Percentage of the memory the process and its children are using, based on resident memory size", .flags = 0, .defaultSortDesc = true, }, + [PERCENT_MEM_GROUP] = { .name = "PERCENT_MEM_GROUP", .title = "GMEM% ", .description = "Percentage of the memory the process is using, based on resident memory size", .flags = 0, .defaultSortDesc = true, }, [USER] = { .name = "USER", .title = "USER ", .description = "Username of the process owner (or user ID if name cannot be determined)", .flags = 0, }, [TIME] = { .name = "TIME", .title = " TIME+ ", .description = "Total time the process has spent in user and system time", .flags = 0, .defaultSortDesc = true, }, [NLWP] = { .name = "NLWP", .title = "NLWP ", .description = "Number of threads in the process", .flags = 0, }, diff --git a/dragonflybsd/DragonFlyBSDProcess.c b/dragonflybsd/DragonFlyBSDProcess.c index a85b6efb0..82ed9507e 100644 --- a/dragonflybsd/DragonFlyBSDProcess.c +++ b/dragonflybsd/DragonFlyBSDProcess.c @@ -39,8 +39,10 @@ const ProcessFieldData Process_fields[LAST_PROCESSFIELD] = { [M_RESIDENT] = { .name = "M_RESIDENT", .title = " RES ", .description = "Resident set size, size of the text and data sections, plus stack usage", .flags = 0, .defaultSortDesc = true, }, [ST_UID] = { .name = "ST_UID", .title = "UID", .description = "User ID of the process owner", .flags = 0, }, [PERCENT_CPU] = { .name = "PERCENT_CPU", .title = " CPU%", .description = "Percentage of the CPU time the process used in the last sampling", .flags = 0, .defaultSortDesc = true, .autoWidth = true, }, + [PERCENT_CPU_GROUP] = { .name = "PERCENT_CPU_GROUP", .title = " GCPU%", .description = "Percentage of the CPU time the process and its children used in the last sampling", .flags = 0, .defaultSortDesc = true, .autoWidth = true, }, [PERCENT_NORM_CPU] = { .name = "PERCENT_NORM_CPU", .title = "NCPU%", .description = "Normalized percentage of the CPU time the process used in the last sampling (normalized by cpu count)", .flags = 0, .defaultSortDesc = true, .autoWidth = true, }, [PERCENT_MEM] = { .name = "PERCENT_MEM", .title = "MEM% ", .description = "Percentage of the memory the process is using, based on resident memory size", .flags = 0, .defaultSortDesc = true, }, + [PERCENT_MEM_GROUP] = { .name = "PERCENT_MEM_GROUP", .title = "GMEM% ", .description = "Percentage of the memory the process and its children are using, based on resident memory size", .flags = 0, .defaultSortDesc = true, }, [USER] = { .name = "USER", .title = "USER ", .description = "Username of the process owner (or user ID if name cannot be determined)", .flags = 0, }, [TIME] = { .name = "TIME", .title = " TIME+ ", .description = "Total time the process has spent in user and system time", .flags = 0, .defaultSortDesc = true, }, [NLWP] = { .name = "NLWP", .title = "NLWP ", .description = "Number of threads in the process", .flags = 0, }, diff --git a/freebsd/FreeBSDProcess.c b/freebsd/FreeBSDProcess.c index f6d3451da..8c07f1362 100644 --- a/freebsd/FreeBSDProcess.c +++ b/freebsd/FreeBSDProcess.c @@ -39,8 +39,10 @@ const ProcessFieldData Process_fields[LAST_PROCESSFIELD] = { [M_RESIDENT] = { .name = "M_RESIDENT", .title = " RES ", .description = "Resident set size, size of the text and data sections, plus stack usage", .flags = 0, .defaultSortDesc = true, }, [ST_UID] = { .name = "ST_UID", .title = "UID", .description = "User ID of the process owner", .flags = 0, }, [PERCENT_CPU] = { .name = "PERCENT_CPU", .title = " CPU%", .description = "Percentage of the CPU time the process used in the last sampling", .flags = 0, .defaultSortDesc = true, .autoWidth = true, }, + [PERCENT_CPU_GROUP] = { .name = "PERCENT_CPU_GROUP", .title = " GCPU%", .description = "Percentage of the CPU time the process and its children used in the last sampling", .flags = 0, .defaultSortDesc = true, .autoWidth = true, }, [PERCENT_NORM_CPU] = { .name = "PERCENT_NORM_CPU", .title = "NCPU%", .description = "Normalized percentage of the CPU time the process used in the last sampling (normalized by cpu count)", .flags = 0, .defaultSortDesc = true, .autoWidth = true, }, [PERCENT_MEM] = { .name = "PERCENT_MEM", .title = "MEM% ", .description = "Percentage of the memory the process is using, based on resident memory size", .flags = 0, .defaultSortDesc = true, }, + [PERCENT_MEM_GROUP] = { .name = "PERCENT_MEM_GROUP", .title = "GMEM% ", .description = "Percentage of the memory the process and its children are using, based on resident memory size", .flags = 0, .defaultSortDesc = true, }, [USER] = { .name = "USER", .title = "USER ", .description = "Username of the process owner (or user ID if name cannot be determined)", .flags = 0, }, [TIME] = { .name = "TIME", .title = " TIME+ ", .description = "Total time the process has spent in user and system time", .flags = 0, .defaultSortDesc = true, }, [NLWP] = { .name = "NLWP", .title = "NLWP ", .description = "Number of threads in the process", .flags = 0, .defaultSortDesc = true, }, diff --git a/htop.1.in b/htop.1.in index d734f4795..70c3157c5 100644 --- a/htop.1.in +++ b/htop.1.in @@ -440,6 +440,12 @@ This is the default way to represent CPU usage in Linux. Each process can consume up to 100% which means the full capacity of the core it is running on. This is sometimes called "Irix mode" e.g. in .BR top (1). +.TP.B PERCENT_CPU_GROUP (GCPU%) +The percentage of the CPU time that the process and its children are currently using. +This is the default way to represent CPU usage in Linux. Each process can +consume up to 100% which means the full capacity of the core it is running +on. This is sometimes called "Irix mode" e.g. in +.BR top (1). .TP .B PERCENT_NORM_CPU (NCPU%) The percentage of the CPU time that the process is currently using normalized @@ -449,6 +455,9 @@ by CPU count. This is sometimes called "Solaris mode" e.g. in .B PERCENT_MEM (MEM%) The percentage of memory the process is currently using (based on the process's resident memory size, see M_RESIDENT above). +.TP.B PERCENT_MEM_GROUP (GMEM%) +The percentage of memory the process and its children are currently using (based on the process's +resident memory size, see M_RESIDENT above). .TP .B USER The username of the process owner, or the user ID if the name can't be diff --git a/linux/LinuxProcess.c b/linux/LinuxProcess.c index 3321f512a..c4eafe058 100644 --- a/linux/LinuxProcess.c +++ b/linux/LinuxProcess.c @@ -56,8 +56,10 @@ const ProcessFieldData Process_fields[LAST_PROCESSFIELD] = { [M_LRS] = { .name = "M_LRS", .title = " LIB ", .description = "The library size of the process (calculated from memory maps)", .flags = PROCESS_FLAG_LINUX_LRS_FIX, .defaultSortDesc = true, }, [ST_UID] = { .name = "ST_UID", .title = "UID", .description = "User ID of the process owner", .flags = 0, }, [PERCENT_CPU] = { .name = "PERCENT_CPU", .title = " CPU%", .description = "Percentage of the CPU time the process used in the last sampling", .flags = 0, .defaultSortDesc = true, .autoWidth = true, }, + [PERCENT_CPU_GROUP] = { .name = "PERCENT_CPU_GROUP", .title = " GCPU%", .description = "Percentage of the CPU time the process and its children used in the last sampling", .flags = 0, .defaultSortDesc = true, .autoWidth = true, }, [PERCENT_NORM_CPU] = { .name = "PERCENT_NORM_CPU", .title = "NCPU%", .description = "Normalized percentage of the CPU time the process used in the last sampling (normalized by cpu count)", .flags = 0, .defaultSortDesc = true, .autoWidth = true, }, [PERCENT_MEM] = { .name = "PERCENT_MEM", .title = "MEM% ", .description = "Percentage of the memory the process is using, based on resident memory size", .flags = 0, .defaultSortDesc = true, }, + [PERCENT_MEM_GROUP] = { .name = "PERCENT_MEM_GROUP", .title = "GMEM% ", .description = "Percentage of the memory the process and its children are using, based on resident memory size", .flags = 0, .defaultSortDesc = true, }, [USER] = { .name = "USER", .title = "USER ", .description = "Username of the process owner (or user ID if name cannot be determined)", .flags = 0, }, [TIME] = { .name = "TIME", .title = " TIME+ ", .description = "Total time the process has spent in user and system time", .flags = 0, .defaultSortDesc = true, }, [NLWP] = { .name = "NLWP", .title = "NLWP ", .description = "Number of threads in the process", .flags = 0, .defaultSortDesc = true, }, diff --git a/netbsd/NetBSDProcess.c b/netbsd/NetBSDProcess.c index 605b56c80..2f1a84548 100644 --- a/netbsd/NetBSDProcess.c +++ b/netbsd/NetBSDProcess.c @@ -150,6 +150,14 @@ const ProcessFieldData Process_fields[LAST_PROCESSFIELD] = { .defaultSortDesc = true, .autoWidth = true, }, + [PERCENT_CPU_GROUP] = { + .name = "PERCENT_CPU_GROUP", + .title = " GCPU%", + .description = "Percentage of the CPU time the process and its children used in the last sampling", + .flags = 0, + .defaultSortDesc = true, + .autoWidth = true, + }, [PERCENT_NORM_CPU] = { .name = "PERCENT_NORM_CPU", .title = "NCPU%", @@ -165,6 +173,13 @@ const ProcessFieldData Process_fields[LAST_PROCESSFIELD] = { .flags = 0, .defaultSortDesc = true, }, + [PERCENT_MEM_GROUP] = { + .name = "PERCENT_MEM_GROUP", + .title = "GMEM% ", + .description = "Percentage of the memory the process and its children are using, based on resident memory size", + .flags = 0, + .defaultSortDesc = true, + }, [USER] = { .name = "USER", .title = "USER ", diff --git a/openbsd/OpenBSDProcess.c b/openbsd/OpenBSDProcess.c index c54a1763b..f9c23315d 100644 --- a/openbsd/OpenBSDProcess.c +++ b/openbsd/OpenBSDProcess.c @@ -148,6 +148,14 @@ const ProcessFieldData Process_fields[LAST_PROCESSFIELD] = { .defaultSortDesc = true, .autoWidth = true, }, + [PERCENT_CPU_GROUP] = { + .name = "PERCENT_CPU_GROUP", + .title = " GCPU%", + .description = "Percentage of the CPU time the process and its children used in the last sampling", + .flags = 0, + .defaultSortDesc = true, + .autoWidth = true, + }, [PERCENT_NORM_CPU] = { .name = "PERCENT_NORM_CPU", .title = "NCPU%", @@ -156,6 +164,13 @@ const ProcessFieldData Process_fields[LAST_PROCESSFIELD] = { .defaultSortDesc = true, .autoWidth = true, }, + [PERCENT_MEM_GROUP] = { + .name = "PERCENT_MEM_GROUP", + .title = "GMEM% ", + .description = "Percentage of the memory the process and its children are using, based on resident memory size", + .flags = 0, + .defaultSortDesc = true, + }, [PERCENT_MEM] = { .name = "PERCENT_MEM", .title = "MEM% ", diff --git a/pcp/PCPProcess.c b/pcp/PCPProcess.c index b54834765..4aeffe29d 100644 --- a/pcp/PCPProcess.c +++ b/pcp/PCPProcess.c @@ -55,8 +55,10 @@ const ProcessFieldData Process_fields[] = { [M_DT] = { .name = "M_DT", .title = " DIRTY ", .description = "Size of the dirty pages of the process (unused since Linux 2.6; always 0)", .flags = 0, .defaultSortDesc = true, }, [ST_UID] = { .name = "ST_UID", .title = "UID", .description = "User ID of the process owner", .flags = 0, }, [PERCENT_CPU] = { .name = "PERCENT_CPU", .title = " CPU%", .description = "Percentage of the CPU time the process used in the last sampling", .flags = 0, .defaultSortDesc = true, .autoWidth = true, }, + [PERCENT_CPU_GROUP] = { .name = "PERCENT_CPU_GROUP", .title = " GCPU%", .description = "Percentage of the CPU time the process and its children used in the last sampling", .flags = 0, .defaultSortDesc = true, .autoWidth = true, }, [PERCENT_NORM_CPU] = { .name = "PERCENT_NORM_CPU", .title = "NCPU%", .description = "Normalized percentage of the CPU time the process used in the last sampling (normalized by cpu count)", .flags = 0, .defaultSortDesc = true, .autoWidth = true, }, [PERCENT_MEM] = { .name = "PERCENT_MEM", .title = "MEM% ", .description = "Percentage of the memory the process is using, based on resident memory size", .flags = 0, .defaultSortDesc = true, }, + [PERCENT_MEM_GROUP] = { .name = "PERCENT_MEM_GROUP", .title = "GMEM% ", .description = "Percentage of the memory the process and its children are using, based on resident memory size", .flags = 0, .defaultSortDesc = true, }, [USER] = { .name = "USER", .title = "USER ", .description = "Username of the process owner (or user ID if name cannot be determined)", .flags = 0, }, [TIME] = { .name = "TIME", .title = " TIME+ ", .description = "Total time the process has spent in user and system time", .flags = 0, .defaultSortDesc = true, }, [NLWP] = { .name = "NLWP", .title = "NLWP ", .description = "Number of threads in the process", .flags = 0, .defaultSortDesc = true, }, diff --git a/solaris/SolarisProcess.c b/solaris/SolarisProcess.c index 35a462d7c..3b67e9c7f 100644 --- a/solaris/SolarisProcess.c +++ b/solaris/SolarisProcess.c @@ -41,8 +41,10 @@ const ProcessFieldData Process_fields[LAST_PROCESSFIELD] = { [M_RESIDENT] = { .name = "M_RESIDENT", .title = " RES ", .description = "Resident set size, size of the text and data sections, plus stack usage", .flags = 0, .defaultSortDesc = true, }, [ST_UID] = { .name = "ST_UID", .title = "UID", .description = "User ID of the process owner", .flags = 0, }, [PERCENT_CPU] = { .name = "PERCENT_CPU", .title = " CPU%", .description = "Percentage of the CPU time the process used in the last sampling", .flags = 0, .defaultSortDesc = true, .autoWidth = true, }, + [PERCENT_CPU_GROUP] = { .name = "PERCENT_CPU_GROUP", .title = " GCPU%", .description = "Percentage of the CPU time the process and its children used in the last sampling", .flags = 0, .defaultSortDesc = true, .autoWidth = true, }, [PERCENT_NORM_CPU] = { .name = "PERCENT_NORM_CPU", .title = "NCPU%", .description = "Normalized percentage of the CPU time the process used in the last sampling (normalized by cpu count)", .flags = 0, .defaultSortDesc = true, .autoWidth = true, }, [PERCENT_MEM] = { .name = "PERCENT_MEM", .title = "MEM% ", .description = "Percentage of the memory the process is using, based on resident memory size", .flags = 0, .defaultSortDesc = true, }, + [PERCENT_MEM_GROUP] = { .name = "PERCENT_MEM_GROUP", .title = "GMEM% ", .description = "Percentage of the memory the process and its children are using, based on resident memory size", .flags = 0, .defaultSortDesc = true, }, [USER] = { .name = "USER", .title = "USER ", .description = "Username of the process owner (or user ID if name cannot be determined)", .flags = 0, }, [TIME] = { .name = "TIME", .title = " TIME+ ", .description = "Total time the process has spent in user and system time", .flags = 0, .defaultSortDesc = true, }, [NLWP] = { .name = "NLWP", .title = "NLWP ", .description = "Number of threads in the process", .flags = 0, }, diff --git a/unsupported/UnsupportedProcess.c b/unsupported/UnsupportedProcess.c index 6df2e36a4..83d7f819a 100644 --- a/unsupported/UnsupportedProcess.c +++ b/unsupported/UnsupportedProcess.c @@ -36,8 +36,10 @@ const ProcessFieldData Process_fields[LAST_PROCESSFIELD] = { [M_RESIDENT] = { .name = "M_RESIDENT", .title = " RES ", .description = "Resident set size, size of the text and data sections, plus stack usage", .flags = 0, .defaultSortDesc = true, }, [ST_UID] = { .name = "ST_UID", .title = "UID", .description = "User ID of the process owner", .flags = 0, }, [PERCENT_CPU] = { .name = "PERCENT_CPU", .title = " CPU%", .description = "Percentage of the CPU time the process used in the last sampling", .flags = 0, .defaultSortDesc = true, .autoWidth = true, }, + [PERCENT_CPU_GROUP] = { .name = "PERCENT_CPU_GROUP", .title = " GCPU%", .description = "Percentage of the CPU time the process and its children used in the last sampling", .flags = 0, .defaultSortDesc = true, .autoWidth = true, }, [PERCENT_NORM_CPU] = { .name = "PERCENT_NORM_CPU", .title = "NCPU%", .description = "Normalized percentage of the CPU time the process used in the last sampling (normalized by cpu count)", .flags = 0, .defaultSortDesc = true, .autoWidth = true, }, [PERCENT_MEM] = { .name = "PERCENT_MEM", .title = "MEM% ", .description = "Percentage of the memory the process is using, based on resident memory size", .flags = 0, .defaultSortDesc = true, }, + [PERCENT_MEM_GROUP] = { .name = "PERCENT_MEM_GROUP", .title = "GMEM% ", .description = "Percentage of the memory the process and its children are using, based on resident memory size", .flags = 0, .defaultSortDesc = true, }, [USER] = { .name = "USER", .title = "USER ", .description = "Username of the process owner (or user ID if name cannot be determined)", .flags = 0, }, [TIME] = { .name = "TIME", .title = " TIME+ ", .description = "Total time the process has spent in user and system time", .flags = 0, .defaultSortDesc = true, }, [NLWP] = { .name = "NLWP", .title = "NLWP ", .description = "Number of threads in the process", .flags = 0, },