mirror of https://github.com/xzeldon/htop.git
Add pressure stall information (PSI) meters on Linux
The pressure stall information (PSI) metrics provide useful information on delays caused by waiting for CPU, IO and memory. Particularly on busy servers it can provide a quick overview of what's "slowing things down". This feature is supported on Linux >= 4.20. The interface is documented here: https://git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git/plain/Documentation/accounting/psi.txt These links provide rationale: https://lwn.net/Articles/759781/ https://facebookmicrosites.github.io/psi/ The following metrics are added, corresponding to the currently exposed lines (see `head /proc/pressure/*`): - PressureStallCPUSome - PressureStallIOSome - PressureStallIOFull - PressureStallMemorySome - PressureStallMemoryFull The color scheme is the same as that used for Load Average, however I gave it separate entries just in case someone wants to change them specifically. Tested on 4.20.7-arch1-1-ARCH, on the linux platform. Also tested that other platforms still compile (changed configure to use the unsupported platform). Closes #879.
This commit is contained in:
parent
402e46bb82
commit
08feb8585b
21
CRT.c
21
CRT.c
|
@ -128,6 +128,9 @@ typedef enum ColorElements_ {
|
||||||
CPU_SOFTIRQ,
|
CPU_SOFTIRQ,
|
||||||
CPU_STEAL,
|
CPU_STEAL,
|
||||||
CPU_GUEST,
|
CPU_GUEST,
|
||||||
|
PRESSURE_STALL_TEN,
|
||||||
|
PRESSURE_STALL_SIXTY,
|
||||||
|
PRESSURE_STALL_THREEHUNDRED,
|
||||||
LAST_COLORELEMENT
|
LAST_COLORELEMENT
|
||||||
} ColorElements;
|
} ColorElements;
|
||||||
|
|
||||||
|
@ -232,6 +235,9 @@ int CRT_colorSchemes[LAST_COLORSCHEME][LAST_COLORELEMENT] = {
|
||||||
[CPU_SOFTIRQ] = ColorPair(Magenta,Black),
|
[CPU_SOFTIRQ] = ColorPair(Magenta,Black),
|
||||||
[CPU_STEAL] = ColorPair(Cyan,Black),
|
[CPU_STEAL] = ColorPair(Cyan,Black),
|
||||||
[CPU_GUEST] = ColorPair(Cyan,Black),
|
[CPU_GUEST] = ColorPair(Cyan,Black),
|
||||||
|
[PRESSURE_STALL_THREEHUNDRED] = ColorPair(Cyan,Black),
|
||||||
|
[PRESSURE_STALL_SIXTY] = A_BOLD | ColorPair(Cyan,Black),
|
||||||
|
[PRESSURE_STALL_TEN] = A_BOLD | ColorPair(White,Black),
|
||||||
},
|
},
|
||||||
[COLORSCHEME_MONOCHROME] = {
|
[COLORSCHEME_MONOCHROME] = {
|
||||||
[RESET_COLOR] = A_NORMAL,
|
[RESET_COLOR] = A_NORMAL,
|
||||||
|
@ -291,6 +297,9 @@ int CRT_colorSchemes[LAST_COLORSCHEME][LAST_COLORELEMENT] = {
|
||||||
[CPU_SOFTIRQ] = A_BOLD,
|
[CPU_SOFTIRQ] = A_BOLD,
|
||||||
[CPU_STEAL] = A_REVERSE,
|
[CPU_STEAL] = A_REVERSE,
|
||||||
[CPU_GUEST] = A_REVERSE,
|
[CPU_GUEST] = A_REVERSE,
|
||||||
|
[PRESSURE_STALL_THREEHUNDRED] = A_DIM,
|
||||||
|
[PRESSURE_STALL_SIXTY] = A_NORMAL,
|
||||||
|
[PRESSURE_STALL_TEN] = A_BOLD,
|
||||||
},
|
},
|
||||||
[COLORSCHEME_BLACKONWHITE] = {
|
[COLORSCHEME_BLACKONWHITE] = {
|
||||||
[RESET_COLOR] = ColorPair(Black,White),
|
[RESET_COLOR] = ColorPair(Black,White),
|
||||||
|
@ -350,6 +359,9 @@ int CRT_colorSchemes[LAST_COLORSCHEME][LAST_COLORELEMENT] = {
|
||||||
[CPU_SOFTIRQ] = ColorPair(Blue,White),
|
[CPU_SOFTIRQ] = ColorPair(Blue,White),
|
||||||
[CPU_STEAL] = ColorPair(Cyan,White),
|
[CPU_STEAL] = ColorPair(Cyan,White),
|
||||||
[CPU_GUEST] = ColorPair(Cyan,White),
|
[CPU_GUEST] = ColorPair(Cyan,White),
|
||||||
|
[PRESSURE_STALL_THREEHUNDRED] = ColorPair(Black,White),
|
||||||
|
[PRESSURE_STALL_SIXTY] = ColorPair(Black,White),
|
||||||
|
[PRESSURE_STALL_TEN] = ColorPair(Black,White),
|
||||||
},
|
},
|
||||||
[COLORSCHEME_LIGHTTERMINAL] = {
|
[COLORSCHEME_LIGHTTERMINAL] = {
|
||||||
[RESET_COLOR] = ColorPair(Black,Black),
|
[RESET_COLOR] = ColorPair(Black,Black),
|
||||||
|
@ -409,6 +421,9 @@ int CRT_colorSchemes[LAST_COLORSCHEME][LAST_COLORELEMENT] = {
|
||||||
[CPU_SOFTIRQ] = ColorPair(Blue,Black),
|
[CPU_SOFTIRQ] = ColorPair(Blue,Black),
|
||||||
[CPU_STEAL] = ColorPair(Black,Black),
|
[CPU_STEAL] = ColorPair(Black,Black),
|
||||||
[CPU_GUEST] = ColorPair(Black,Black),
|
[CPU_GUEST] = ColorPair(Black,Black),
|
||||||
|
[PRESSURE_STALL_THREEHUNDRED] = ColorPair(Black,Black),
|
||||||
|
[PRESSURE_STALL_SIXTY] = ColorPair(Black,Black),
|
||||||
|
[PRESSURE_STALL_TEN] = ColorPair(Black,Black),
|
||||||
},
|
},
|
||||||
[COLORSCHEME_MIDNIGHT] = {
|
[COLORSCHEME_MIDNIGHT] = {
|
||||||
[RESET_COLOR] = ColorPair(White,Blue),
|
[RESET_COLOR] = ColorPair(White,Blue),
|
||||||
|
@ -468,6 +483,9 @@ int CRT_colorSchemes[LAST_COLORSCHEME][LAST_COLORELEMENT] = {
|
||||||
[CPU_SOFTIRQ] = ColorPair(Black,Blue),
|
[CPU_SOFTIRQ] = ColorPair(Black,Blue),
|
||||||
[CPU_STEAL] = ColorPair(White,Blue),
|
[CPU_STEAL] = ColorPair(White,Blue),
|
||||||
[CPU_GUEST] = ColorPair(White,Blue),
|
[CPU_GUEST] = ColorPair(White,Blue),
|
||||||
|
[PRESSURE_STALL_THREEHUNDRED] = A_BOLD | ColorPair(Black,Blue),
|
||||||
|
[PRESSURE_STALL_SIXTY] = A_NORMAL | ColorPair(White,Blue),
|
||||||
|
[PRESSURE_STALL_TEN] = A_BOLD | ColorPair(White,Blue),
|
||||||
},
|
},
|
||||||
[COLORSCHEME_BLACKNIGHT] = {
|
[COLORSCHEME_BLACKNIGHT] = {
|
||||||
[RESET_COLOR] = ColorPair(Cyan,Black),
|
[RESET_COLOR] = ColorPair(Cyan,Black),
|
||||||
|
@ -527,6 +545,9 @@ int CRT_colorSchemes[LAST_COLORSCHEME][LAST_COLORELEMENT] = {
|
||||||
[CPU_SOFTIRQ] = ColorPair(Blue,Black),
|
[CPU_SOFTIRQ] = ColorPair(Blue,Black),
|
||||||
[CPU_STEAL] = ColorPair(Cyan,Black),
|
[CPU_STEAL] = ColorPair(Cyan,Black),
|
||||||
[CPU_GUEST] = ColorPair(Cyan,Black),
|
[CPU_GUEST] = ColorPair(Cyan,Black),
|
||||||
|
[PRESSURE_STALL_THREEHUNDRED] = ColorPair(Green,Black),
|
||||||
|
[PRESSURE_STALL_SIXTY] = ColorPair(Green,Black),
|
||||||
|
[PRESSURE_STALL_TEN] = A_BOLD | ColorPair(Green,Black),
|
||||||
},
|
},
|
||||||
[COLORSCHEME_BROKENGRAY] = { 0 } // dynamically generated.
|
[COLORSCHEME_BROKENGRAY] = { 0 } // dynamically generated.
|
||||||
};
|
};
|
||||||
|
|
3
CRT.h
3
CRT.h
|
@ -116,6 +116,9 @@ typedef enum ColorElements_ {
|
||||||
CPU_SOFTIRQ,
|
CPU_SOFTIRQ,
|
||||||
CPU_STEAL,
|
CPU_STEAL,
|
||||||
CPU_GUEST,
|
CPU_GUEST,
|
||||||
|
PRESSURE_STALL_TEN,
|
||||||
|
PRESSURE_STALL_SIXTY,
|
||||||
|
PRESSURE_STALL_THREEHUNDRED,
|
||||||
LAST_COLORELEMENT
|
LAST_COLORELEMENT
|
||||||
} ColorElements;
|
} ColorElements;
|
||||||
|
|
||||||
|
|
|
@ -48,14 +48,16 @@ linux_platform_headers = \
|
||||||
linux/LinuxProcess.h \
|
linux/LinuxProcess.h \
|
||||||
linux/LinuxProcessList.h \
|
linux/LinuxProcessList.h \
|
||||||
linux/LinuxCRT.h \
|
linux/LinuxCRT.h \
|
||||||
linux/Battery.h
|
linux/Battery.h \
|
||||||
|
linux/PressureStallMeter.h
|
||||||
|
|
||||||
all_platform_headers += $(linux_platform_headers)
|
all_platform_headers += $(linux_platform_headers)
|
||||||
|
|
||||||
if HTOP_LINUX
|
if HTOP_LINUX
|
||||||
AM_CFLAGS += -rdynamic
|
AM_CFLAGS += -rdynamic
|
||||||
myhtopplatsources = linux/Platform.c linux/IOPriorityPanel.c linux/IOPriority.c \
|
myhtopplatsources = linux/Platform.c linux/IOPriorityPanel.c linux/IOPriority.c \
|
||||||
linux/LinuxProcess.c linux/LinuxProcessList.c linux/LinuxCRT.c linux/Battery.c
|
linux/LinuxProcess.c linux/LinuxProcessList.c linux/LinuxCRT.c linux/Battery.c \
|
||||||
|
linux/PressureStallMeter.c
|
||||||
|
|
||||||
myhtopplatheaders = $(linux_platform_headers)
|
myhtopplatheaders = $(linux_platform_headers)
|
||||||
endif
|
endif
|
||||||
|
|
|
@ -19,6 +19,7 @@ in the source distribution for its full text.
|
||||||
#include "TasksMeter.h"
|
#include "TasksMeter.h"
|
||||||
#include "LoadAverageMeter.h"
|
#include "LoadAverageMeter.h"
|
||||||
#include "UptimeMeter.h"
|
#include "UptimeMeter.h"
|
||||||
|
#include "PressureStallMeter.h"
|
||||||
#include "ClockMeter.h"
|
#include "ClockMeter.h"
|
||||||
#include "HostnameMeter.h"
|
#include "HostnameMeter.h"
|
||||||
#include "LinuxProcess.h"
|
#include "LinuxProcess.h"
|
||||||
|
@ -126,6 +127,11 @@ MeterClass* Platform_meterTypes[] = {
|
||||||
&LeftCPUs2Meter_class,
|
&LeftCPUs2Meter_class,
|
||||||
&RightCPUs2Meter_class,
|
&RightCPUs2Meter_class,
|
||||||
&BlankMeter_class,
|
&BlankMeter_class,
|
||||||
|
&PressureStallCPUSomeMeter_class,
|
||||||
|
&PressureStallIOSomeMeter_class,
|
||||||
|
&PressureStallIOFullMeter_class,
|
||||||
|
&PressureStallMemorySomeMeter_class,
|
||||||
|
&PressureStallMemoryFullMeter_class,
|
||||||
NULL
|
NULL
|
||||||
};
|
};
|
||||||
|
|
||||||
|
@ -237,3 +243,21 @@ char* Platform_getProcessEnv(pid_t pid) {
|
||||||
}
|
}
|
||||||
return env;
|
return env;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void Platform_getPressureStall(const char *file, bool some, double* ten, double* sixty, double* threehundred) {
|
||||||
|
*ten = *sixty = *threehundred = 0;
|
||||||
|
char procname[128+1];
|
||||||
|
xSnprintf(procname, 128, PROCDIR "/pressure/%s", file);
|
||||||
|
FILE *fd = fopen(procname, "r");
|
||||||
|
if (!fd) {
|
||||||
|
*ten = *sixty = *threehundred = NAN;
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
int total = fscanf(fd, "some avg10=%32lf avg60=%32lf avg300=%32lf total=%*f ", ten, sixty, threehundred);
|
||||||
|
if (!some) {
|
||||||
|
total = fscanf(fd, "full avg10=%32lf avg60=%32lf avg300=%32lf total=%*f ", ten, sixty, threehundred);
|
||||||
|
}
|
||||||
|
(void) total;
|
||||||
|
assert(total == 3);
|
||||||
|
fclose(fd);
|
||||||
|
}
|
||||||
|
|
|
@ -45,4 +45,6 @@ void Platform_setSwapValues(Meter* this);
|
||||||
|
|
||||||
char* Platform_getProcessEnv(pid_t pid);
|
char* Platform_getProcessEnv(pid_t pid);
|
||||||
|
|
||||||
|
void Platform_getPressureStall(const char *file, bool some, double* ten, double* sixty, double* threehundred);
|
||||||
|
|
||||||
#endif
|
#endif
|
||||||
|
|
|
@ -0,0 +1,133 @@
|
||||||
|
/*
|
||||||
|
htop - PressureStallMeter.c
|
||||||
|
(C) 2004-2011 Hisham H. Muhammad
|
||||||
|
(C) 2019 Ran Benita
|
||||||
|
Released under the GNU GPL, see the COPYING file
|
||||||
|
in the source distribution for its full text.
|
||||||
|
*/
|
||||||
|
|
||||||
|
#include "PressureStallMeter.h"
|
||||||
|
#include "Platform.h"
|
||||||
|
#include "CRT.h"
|
||||||
|
|
||||||
|
#include <string.h>
|
||||||
|
|
||||||
|
/*{
|
||||||
|
#include "Meter.h"
|
||||||
|
}*/
|
||||||
|
|
||||||
|
static int PressureStallMeter_attributes[] = {
|
||||||
|
PRESSURE_STALL_TEN, PRESSURE_STALL_SIXTY, PRESSURE_STALL_THREEHUNDRED
|
||||||
|
};
|
||||||
|
|
||||||
|
static void PressureStallMeter_updateValues(Meter* this, char* buffer, int len) {
|
||||||
|
const char *file;
|
||||||
|
if (strstr(Meter_name(this), "CPU")) {
|
||||||
|
file = "cpu";
|
||||||
|
} else if (strstr(Meter_name(this), "IO")) {
|
||||||
|
file = "io";
|
||||||
|
} else {
|
||||||
|
file = "memory";
|
||||||
|
}
|
||||||
|
|
||||||
|
bool some;
|
||||||
|
if (strstr(Meter_name(this), "Some")) {
|
||||||
|
some = true;
|
||||||
|
} else {
|
||||||
|
some = false;
|
||||||
|
}
|
||||||
|
|
||||||
|
Platform_getPressureStall(file, some, &this->values[0], &this->values[1], &this->values[2]);
|
||||||
|
xSnprintf(buffer, len, "xxxx %.2lf%% %.2lf%% %.2lf%%", this->values[0], this->values[1], this->values[2]);
|
||||||
|
}
|
||||||
|
|
||||||
|
static void PressureStallMeter_display(Object* cast, RichString* out) {
|
||||||
|
Meter* this = (Meter*)cast;
|
||||||
|
char buffer[20];
|
||||||
|
xSnprintf(buffer, sizeof(buffer), "%.2lf%% ", this->values[0]);
|
||||||
|
RichString_write(out, CRT_colors[PRESSURE_STALL_TEN], buffer);
|
||||||
|
xSnprintf(buffer, sizeof(buffer), "%.2lf%% ", this->values[1]);
|
||||||
|
RichString_append(out, CRT_colors[PRESSURE_STALL_SIXTY], buffer);
|
||||||
|
xSnprintf(buffer, sizeof(buffer), "%.2lf%% ", this->values[2]);
|
||||||
|
RichString_append(out, CRT_colors[PRESSURE_STALL_THREEHUNDRED], buffer);
|
||||||
|
}
|
||||||
|
|
||||||
|
MeterClass PressureStallCPUSomeMeter_class = {
|
||||||
|
.super = {
|
||||||
|
.extends = Class(Meter),
|
||||||
|
.delete = Meter_delete,
|
||||||
|
.display = PressureStallMeter_display,
|
||||||
|
},
|
||||||
|
.updateValues = PressureStallMeter_updateValues,
|
||||||
|
.defaultMode = TEXT_METERMODE,
|
||||||
|
.maxItems = 3,
|
||||||
|
.total = 100.0,
|
||||||
|
.attributes = PressureStallMeter_attributes,
|
||||||
|
.name = "PressureStallCPUSome",
|
||||||
|
.uiName = "Pressure Stall Information, some CPU",
|
||||||
|
.caption = "Some CPU pressure: "
|
||||||
|
};
|
||||||
|
|
||||||
|
MeterClass PressureStallIOSomeMeter_class = {
|
||||||
|
.super = {
|
||||||
|
.extends = Class(Meter),
|
||||||
|
.delete = Meter_delete,
|
||||||
|
.display = PressureStallMeter_display,
|
||||||
|
},
|
||||||
|
.updateValues = PressureStallMeter_updateValues,
|
||||||
|
.defaultMode = TEXT_METERMODE,
|
||||||
|
.maxItems = 3,
|
||||||
|
.total = 100.0,
|
||||||
|
.attributes = PressureStallMeter_attributes,
|
||||||
|
.name = "PressureStallIOSome",
|
||||||
|
.uiName = "Pressure Stall Information, some IO",
|
||||||
|
.caption = "Some IO pressure: "
|
||||||
|
};
|
||||||
|
|
||||||
|
MeterClass PressureStallIOFullMeter_class = {
|
||||||
|
.super = {
|
||||||
|
.extends = Class(Meter),
|
||||||
|
.delete = Meter_delete,
|
||||||
|
.display = PressureStallMeter_display,
|
||||||
|
},
|
||||||
|
.updateValues = PressureStallMeter_updateValues,
|
||||||
|
.defaultMode = TEXT_METERMODE,
|
||||||
|
.maxItems = 3,
|
||||||
|
.total = 100.0,
|
||||||
|
.attributes = PressureStallMeter_attributes,
|
||||||
|
.name = "PressureStallIOFull",
|
||||||
|
.uiName = "Pressure Stall Information, full IO",
|
||||||
|
.caption = "Full IO pressure: "
|
||||||
|
};
|
||||||
|
|
||||||
|
MeterClass PressureStallMemorySomeMeter_class = {
|
||||||
|
.super = {
|
||||||
|
.extends = Class(Meter),
|
||||||
|
.delete = Meter_delete,
|
||||||
|
.display = PressureStallMeter_display,
|
||||||
|
},
|
||||||
|
.updateValues = PressureStallMeter_updateValues,
|
||||||
|
.defaultMode = TEXT_METERMODE,
|
||||||
|
.maxItems = 3,
|
||||||
|
.total = 100.0,
|
||||||
|
.attributes = PressureStallMeter_attributes,
|
||||||
|
.name = "PressureStallMemorySome",
|
||||||
|
.uiName = "Pressure Stall Information, some memory",
|
||||||
|
.caption = "Some Mem pressure: "
|
||||||
|
};
|
||||||
|
|
||||||
|
MeterClass PressureStallMemoryFullMeter_class = {
|
||||||
|
.super = {
|
||||||
|
.extends = Class(Meter),
|
||||||
|
.delete = Meter_delete,
|
||||||
|
.display = PressureStallMeter_display,
|
||||||
|
},
|
||||||
|
.updateValues = PressureStallMeter_updateValues,
|
||||||
|
.defaultMode = TEXT_METERMODE,
|
||||||
|
.maxItems = 3,
|
||||||
|
.total = 100.0,
|
||||||
|
.attributes = PressureStallMeter_attributes,
|
||||||
|
.name = "PressureStallMemoryFull",
|
||||||
|
.uiName = "Pressure Stall Information, full memory",
|
||||||
|
.caption = "Full Mem pressure: "
|
||||||
|
};
|
|
@ -0,0 +1,25 @@
|
||||||
|
/* Do not edit this file. It was automatically generated. */
|
||||||
|
|
||||||
|
#ifndef HEADER_PressureStallMeter
|
||||||
|
#define HEADER_PressureStallMeter
|
||||||
|
/*
|
||||||
|
htop - PressureStallMeter.h
|
||||||
|
(C) 2004-2011 Hisham H. Muhammad
|
||||||
|
(C) 2019 Ran Benita
|
||||||
|
Released under the GNU GPL, see the COPYING file
|
||||||
|
in the source distribution for its full text.
|
||||||
|
*/
|
||||||
|
|
||||||
|
#include "Meter.h"
|
||||||
|
|
||||||
|
extern MeterClass PressureStallCPUSomeMeter_class;
|
||||||
|
|
||||||
|
extern MeterClass PressureStallIOSomeMeter_class;
|
||||||
|
|
||||||
|
extern MeterClass PressureStallIOFullMeter_class;
|
||||||
|
|
||||||
|
extern MeterClass PressureStallMemorySomeMeter_class;
|
||||||
|
|
||||||
|
extern MeterClass PressureStallMemoryFullMeter_class;
|
||||||
|
|
||||||
|
#endif
|
Loading…
Reference in New Issue