Skip to content
Open
Show file tree
Hide file tree
Changes from all 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
12 changes: 10 additions & 2 deletions Row.c
Original file line number Diff line number Diff line change
Expand Up @@ -492,7 +492,7 @@ void Row_printNanoseconds(RichString* str, unsigned long long totalNanoseconds,
Row_printTime(str, totalHundredths, coloring);
}

void Row_printRate(RichString* str, double rate, bool coloring) {
static void Row_printRateUnit(RichString* str, double rate, bool coloring, char unit) {
char buffer[16];

int largeNumberColor = CRT_colors[LARGE_NUMBER];
Expand Down Expand Up @@ -525,11 +525,19 @@ void Row_printRate(RichString* str, double rate, bool coloring) {
else if (i >= 3)
color = largeNumberColor;

char prefix = (i == 0) ? 'B' : unitPrefixes[i - 1];
char prefix = (i == 0) ? unit : unitPrefixes[i - 1];
int len = xSnprintf(buffer, sizeof(buffer), "%7.2f %c/s ", scaled, prefix);
RichString_appendnAscii(str, color, buffer, len);
}

void Row_printRate(RichString* str, double rate, bool coloring) {
Row_printRateUnit(str, rate, coloring, 'B');
}

void Row_printCountRate(RichString* str, double rate, bool coloring) {
Row_printRateUnit(str, rate, coloring, 'o');
}

void Row_printLeftAlignedField(RichString* str, int attr, const char* content, unsigned int width) {
int columns = width;
RichString_appendnWideColumns(str, attr, content, strlen(content), &columns);
Expand Down
3 changes: 3 additions & 0 deletions Row.h
Original file line number Diff line number Diff line change
Expand Up @@ -164,6 +164,9 @@ void Row_printNanoseconds(RichString* str, unsigned long long totalNanoseconds,
/* Takes rate in bare unit (base 1024) per second. Prints 12 columns. */
void Row_printRate(RichString* str, double rate, bool coloring);

/* Takes a per-second count (base 1024) of operations. Prints 12 columns. */
void Row_printCountRate(RichString* str, double rate, bool coloring);

int Row_printPercentage(float val, char* buffer, size_t n, uint8_t width, int* attr);

static inline int Row_idEqualCompare(const void* v1, const void* v2) {
Expand Down
38 changes: 38 additions & 0 deletions freebsd/FreeBSDProcess.c
Original file line number Diff line number Diff line change
Expand Up @@ -9,13 +9,15 @@ in the source distribution for its full text.

#include "freebsd/FreeBSDProcess.h"

#include <math.h>
#include <stdlib.h>

#include "CRT.h"
#include "Macros.h"
#include "Process.h"
#include "RichString.h"
#include "Scheduling.h"
#include "Settings.h"
#include "XUtils.h"


Expand Down Expand Up @@ -57,6 +59,9 @@ const ProcessFieldData Process_fields[LAST_PROCESSFIELD] = {
[JAIL] = { .name = "JAIL", .title = "JAIL ", .description = "Jail prison name", .flags = 0, },
[SCHEDCLASS] = { .name = "SCHEDCLASS", .title = "SC", .description = "Scheduling Class (Timesharing, Realtime, Idletime)", .flags = 0, },
[EMULATION] = { .name = "EMULATION", .title = "EMULATION ", .description = "System call emulation environment (ABI)", .flags = 0, },
[IO_READ_OPS] = { .name = "IO_READ_OPS", .title = " IO READ ", .description = "The I/O read block operations per second for the process", .flags = PROCESS_FLAG_IO, .defaultSortDesc = true, },
[IO_WRITE_OPS] = { .name = "IO_WRITE_OPS", .title = " IO WRITE ", .description = "The I/O write block operations per second for the process", .flags = PROCESS_FLAG_IO, .defaultSortDesc = true, },
[IO_OPS] = { .name = "IO_OPS", .title = " IO R/W ", .description = "Total I/O block operations per second", .flags = PROCESS_FLAG_IO, .defaultSortDesc = true, },
};

Process* FreeBSDProcess_new(const Machine* machine) {
Expand All @@ -82,9 +87,24 @@ static const char FreeBSD_schedclassChars[MAX_SCHEDCLASS] = {
[SCHEDCLASS_REALTIME] = 'r', // realtime scheduling
};

static double FreeBSDProcess_totalIOOps(const FreeBSDProcess* fp) {
double totalOps = NAN;
if (isNonnegative(fp->io_read_ops)) {
totalOps = fp->io_read_ops;
if (isNonnegative(fp->io_write_ops)) {
totalOps += fp->io_write_ops;
}
} else if (isNonnegative(fp->io_write_ops)) {
totalOps = fp->io_write_ops;
}
return totalOps;
}

static void FreeBSDProcess_rowWriteField(const Row* super, RichString* str, ProcessField field) {
const FreeBSDProcess* fp = (const FreeBSDProcess*) super;
const Machine* host = (const Machine*) super->host;

bool coloring = host->settings->highlightMegabytes;
char buffer[256]; buffer[255] = '\0';
char sched_class;
int attr = CRT_colors[DEFAULT_COLOR];
Expand All @@ -109,6 +129,18 @@ static void FreeBSDProcess_rowWriteField(const Row* super, RichString* str, Proc
xSnprintf(buffer, n, " %c", sched_class);
break;

case IO_READ_OPS:
Row_printCountRate(str, fp->io_read_ops, coloring);
return;

case IO_WRITE_OPS:
Row_printCountRate(str, fp->io_write_ops, coloring);
return;

case IO_OPS:
Row_printCountRate(str, FreeBSDProcess_totalIOOps(fp), coloring);
return;

default:
Process_writeField(&fp->super, str, field);
return;
Expand All @@ -131,6 +163,12 @@ static int FreeBSDProcess_compareByKey(const Process* v1, const Process* v2, Pro
return SPACESHIP_NULLSTR(p1->emul, p2->emul);
case SCHEDCLASS:
return SPACESHIP_NUMBER(p1->sched_class, p2->sched_class);
case IO_READ_OPS:
return compareRealNumbers(p1->io_read_ops, p2->io_read_ops);
case IO_WRITE_OPS:
return compareRealNumbers(p1->io_write_ops, p2->io_write_ops);
case IO_OPS:
return compareRealNumbers(FreeBSDProcess_totalIOOps(p1), FreeBSDProcess_totalIOOps(p2));
default:
return Process_compareByKey_Base(v1, v2, key);
}
Expand Down
8 changes: 8 additions & 0 deletions freebsd/FreeBSDProcess.h
Original file line number Diff line number Diff line change
Expand Up @@ -8,6 +8,7 @@ in the source distribution for its full text.
*/

#include <stdbool.h>
#include <sys/time.h>

#include "Object.h"
#include "Process.h"
Expand All @@ -30,6 +31,13 @@ typedef struct FreeBSDProcess_ {
char* jname;
char* emul;
FreeBSDSchedClass sched_class;

unsigned long long io_last_inblock; /* cumulative block read ops at last sample */
unsigned long long io_last_oublock; /* cumulative block write ops at last sample */
unsigned long long io_last_scan_time_ms; /* time of last I/O sample, ms since the Epoch */
struct timeval io_process_start; /* start time of the sampled process, to detect PID reuse */
double io_read_ops; /* block read operations per second */
double io_write_ops; /* block write operations per second */
} FreeBSDProcess;

extern const ProcessClass FreeBSDProcess_class;
Expand Down
19 changes: 19 additions & 0 deletions freebsd/FreeBSDProcessTable.c
Original file line number Diff line number Diff line change
Expand Up @@ -306,6 +306,25 @@ void ProcessTable_goThroughEntries(ProcessTable* super) {
default: proc->state = UNKNOWN;
}

/* Storage I/O rates, derived from the rusage block-operation counters
* (same source as the FreeBSD top(1) "-m io" mode). */
unsigned long long ioIn = (unsigned long long)kproc->ki_rusage.ru_inblock;
unsigned long long ioOut = (unsigned long long)kproc->ki_rusage.ru_oublock;
unsigned long long ioTimeDelta = saturatingSub(host->realtimeMs, fp->io_last_scan_time_ms);
bool sameProcess = fp->io_process_start.tv_sec == kproc->ki_start.tv_sec &&
fp->io_process_start.tv_usec == kproc->ki_start.tv_usec;
if (preExisting && sameProcess && fp->io_last_scan_time_ms && ioTimeDelta) {
fp->io_read_ops = saturatingSub(ioIn, fp->io_last_inblock) * /*ms to s*/1000.0 / ioTimeDelta;
fp->io_write_ops = saturatingSub(ioOut, fp->io_last_oublock) * /*ms to s*/1000.0 / ioTimeDelta;
} else {
fp->io_read_ops = NAN;
fp->io_write_ops = NAN;
}
fp->io_last_inblock = ioIn;
fp->io_last_oublock = ioOut;
fp->io_last_scan_time_ms = host->realtimeMs;
fp->io_process_start = kproc->ki_start;

if (Process_isKernelThread(proc))
super->kernelThreads++;

Expand Down
5 changes: 5 additions & 0 deletions freebsd/Platform.c
Original file line number Diff line number Diff line change
Expand Up @@ -55,6 +55,11 @@ const ScreenDefaults Platform_defaultScreens[] = {
.columns = "PID USER PRIORITY NICE M_VIRT M_RESIDENT STATE PERCENT_CPU PERCENT_MEM TIME Command",
.sortKey = "PERCENT_CPU",
},
{
.name = "I/O",
.columns = "PID USER IO_OPS IO_READ_OPS IO_WRITE_OPS Command",
.sortKey = "IO_OPS",
},
};

const unsigned int Platform_numberOfDefaultScreens = ARRAYSIZE(Platform_defaultScreens);
Expand Down
3 changes: 3 additions & 0 deletions freebsd/ProcessField.h
Original file line number Diff line number Diff line change
Expand Up @@ -13,6 +13,9 @@ in the source distribution for its full text.
JAIL = 101, \
EMULATION = 102, \
SCHEDCLASS = 103, \
IO_READ_OPS = 104, \
IO_WRITE_OPS = 105, \
IO_OPS = 106, \
\
DUMMY_BUMP_FIELD = CWD, \
// End of list
Expand Down
9 changes: 9 additions & 0 deletions htop.1.in
Original file line number Diff line number Diff line change
Expand Up @@ -603,6 +603,15 @@ The I/O rate of write(2) in bytes per second, for the process.
.B IO_RATE (DISK R/W)
The I/O rate, IO_READ_RATE + IO_WRITE_RATE (see above).
.TP
.B IO_READ_OPS (IO READ)
The I/O rate of block read operations per second, for the process (FreeBSD).
.TP
.B IO_WRITE_OPS (IO WRITE)
The I/O rate of block write operations per second, for the process (FreeBSD).
.TP
.B IO_OPS (IO R/W)
The total I/O rate, IO_READ_OPS + IO_WRITE_OPS (see above) (FreeBSD).
.TP
.B CGROUP
Which cgroup the process is in. For a shortened view see the CCGROUP column below.
.TP
Expand Down