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
9 changes: 8 additions & 1 deletion src/hotspot/os/linux/vitals_linux.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -106,6 +106,8 @@ static Column* g_col_system_num_threads = nullptr;
static Column* g_col_system_num_procs_running = nullptr;
static Column* g_col_system_num_procs_blocked = nullptr;

static Column* g_col_system_load_avg = nullptr;

static bool g_show_cgroup_info = false;
static Column* g_col_system_cgrp_limit_in_bytes = nullptr;
static Column* g_col_system_cgrp_soft_limit_in_bytes = nullptr;
Expand Down Expand Up @@ -176,10 +178,13 @@ bool platform_columns_initialize() {
define_column<PlainValueColumn>(system_cat, nullptr, "t", "Number of threads", true);

g_col_system_num_procs_running =
define_column<PlainValueColumn>(system_cat, nullptr, "tr", "Number of threads running", true);
define_column<PlainValueColumn>(system_cat, nullptr, "tr", "Number of running and runnable threads", true);
g_col_system_num_procs_blocked =
define_column<PlainValueColumn>(system_cat, nullptr, "tb", "Number of threads blocked on disk IO", true);

g_col_system_load_avg =
define_column<LoadAverageColumn>(system_cat, nullptr, "la", "Load average in percent", true, MAX);

g_col_system_cpu_user =
define_column<CPUTimeColumn>(system_cat, "cpu", "us", "CPU user time [host]", true);
g_col_system_cpu_system =
Expand Down Expand Up @@ -287,6 +292,8 @@ void sample_platform_values(Sample* sample) {
set_value_in_sample(g_col_system_num_procs_running, sample, OSWrapper::syst_tr());
set_value_in_sample(g_col_system_num_procs_blocked, sample, OSWrapper::syst_tb());

set_value_in_sample(g_col_system_load_avg, sample, OSWrapper::syst_ldavg());

// cgroups business
if (g_show_cgroup_info) {
set_value_in_sample(g_col_system_cgrp_usage_in_bytes, sample, OSWrapper::syst_cgro_usg());
Expand Down
27 changes: 25 additions & 2 deletions src/hotspot/os/linux/vitals_linux_oswrapper.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -35,7 +35,6 @@
#include <fcntl.h>
#include <string.h>


#define LOG_HERE_F(msg, ...) { printf("[%d] ", (int)::getpid()); ::printf(msg, __VA_ARGS__); printf("\n"); fflush(stdout); }
#define LOG_HERE(msg) { printf("[%d] ", (int)::getpid()); ::printf("%s", msg); printf("\n"); fflush(stdout); }

Expand Down Expand Up @@ -371,6 +370,7 @@ const char* CGroups::_file_lim = nullptr;
const char* CGroups::_file_limsw = nullptr;
const char* CGroups::_file_slim = nullptr;
const char* CGroups::_file_kusg = nullptr;
double proc_scale_factor = 0.0;

void OSWrapper::update_if_needed() {

Expand All @@ -394,6 +394,7 @@ ALL_VALUES_DO(RESETVAL)

if (first_call) {
log_trace(vitals)("Read /proc/meminfo: \n%s", bf.text());
proc_scale_factor = 100.0 / MAX2(1, os::processor_count());
Comment thread
MBaesken marked this conversation as resolved.
}

// All values in /proc/meminfo are in KB
Expand Down Expand Up @@ -436,7 +437,7 @@ ALL_VALUES_DO(RESETVAL)
_syst_cpu_st = values.steal;
_syst_cpu_gu = values.guest + values.guest_nice;

// procs_running: this is actually number of threads running
// procs_running: this is running and runnable threads.
// procs_blocked: number of threads blocked on real disk IO
// See https://utcc.utoronto.ca/~cks/space/blog/linux/ProcessStatesAndProcStat
// and https://lore.kernel.org/lkml/12601530441257@xenotime.net/#t
Expand Down Expand Up @@ -556,6 +557,28 @@ ALL_VALUES_DO(RESETVAL)
}
#endif // __GLIBC__

if (bf.read("/proc/loadavg")) {
float l1, l5, l15;
if (sscanf(bf.text(), "%f %f %f", &l1, &l5, &l15) == 3) {
// Convert to relative percentage-based loads, where 100 percent
// means the number of runnable threads equals the number of CPUs.
value_t rl1 = (value_t) MAX2(0.0, MIN2(65535.0, proc_scale_factor * l1));
value_t rl5 = (value_t) MAX2(0.0, MIN2(65535.0, proc_scale_factor * l5));
value_t rl15 = (value_t) MAX2(0.0, MIN2(65535.0, proc_scale_factor * l15));
// We put the three values into one, since we want to display
// the longer averaged one in table with coarser resolution.
_syst_ldavg = (rl1 << 32) | (rl5 << 16) | rl15;

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

How meaningful will this be in the "Last 60 minutes section" with 10 seconds interval?

Copy link
Copy Markdown
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

In the 10 second interval table the 1 minute average will be used, which covers 6 times the sample interval. While not ideal, it is easy to see the general change of the load compared to the previous sample.

} else {
_syst_ldavg = INVALID_VALUE;
Comment thread
MBaesken marked this conversation as resolved.
static bool traced = false;

if (!traced) {
log_trace(vitals)("Could not parse /proc/loadavg: \n%s", bf.text());
traced = true;
}
}
}

first_call = false;

}
Expand Down
1 change: 1 addition & 0 deletions src/hotspot/os/linux/vitals_linux_oswrapper.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -48,6 +48,7 @@ class OSWrapper {
f(syst_t) \
f(syst_tr) \
f(syst_tb) \
f(syst_ldavg) \
f(syst_cpu_us) \
f(syst_cpu_sy) \
f(syst_cpu_id) \
Expand Down
32 changes: 31 additions & 1 deletion src/hotspot/share/vitals/vitals.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -551,13 +551,17 @@ int Column::do_print(outputStream* st, value_t value, value_t last_value,
}
} else {
if (pi->raw) {
return printf_helper(st, UINT64_FORMAT, value);
return do_print_raw0(st, value);
} else {
return do_print0(st, value, last_value, last_value_age, pi);
}
}
}

int Column::do_print_raw0(outputStream* st, value_t value) const {
return printf_helper(st, UINT64_FORMAT, value);
}

int PlainValueColumn::do_print0(outputStream* st, value_t value,
value_t last_value, int last_value_age, const print_info_t* pi) const
{
Expand Down Expand Up @@ -591,6 +595,32 @@ int DeltaMemorySizeColumn::do_print0(outputStream* st, value_t value,
return 0;
}

int LoadAverageColumn::do_print0(outputStream* st, value_t value,
value_t last_value, int last_value_age, const print_info_t* pi) const {
if (value != INVALID_VALUE) {
value_t load_average;

// Use the minute resolution until an age of 2.5 minutes
// and 5 minute resolution until an age of 7.5 minutes.
// The extremes use last_value_age, so they use the one minute average.
if (last_value_age <= 150) {
load_average = value >> 32;
} else if (last_value_age < 450) {
load_average = (value >> 16) & 0xffff;
} else {
load_average = value & 0xffff;
}

return printf_helper(st, UINT64_FORMAT, load_average);
}

return 0;
}

int LoadAverageColumn::do_print_raw0(outputStream* st, value_t value) const {
return do_print0(st, value, INVALID_VALUE, 0, nullptr);
}

////////////// sample printing ///////////////////////////

// Print one sample.
Expand Down
13 changes: 13 additions & 0 deletions src/hotspot/share/vitals/vitals_internals.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -93,6 +93,8 @@ namespace sapmachine_vitals {
// output stream can be nullptr; in that case, method shall return number of characters it would have printed.
virtual int do_print0(outputStream* os, value_t value,
value_t last_value, int last_value_age, const print_info_t* pi) const = 0;
// Can be overridden by the implementation. By default writes the 64 bit value.
virtual int do_print_raw0(outputStream* os, value_t value) const;

public:

Expand Down Expand Up @@ -171,6 +173,17 @@ namespace sapmachine_vitals {
{}
};

// Special column which can handle the 3 load averages in the raw value.
class LoadAverageColumn: public Column {
int do_print0(outputStream* os, value_t value, value_t last_value,
int last_value_age, const print_info_t* pi) const;
int do_print_raw0(outputStream* os, value_t value) const;
public:
LoadAverageColumn(const char* category, const char* header, const char* name, const char* description, Extremum extremum)
: Column(category, header, name, description, extremum)
{}
};

////// Legend: handles the legend

class Legend: public CHeapObj<mtInternal> {
Expand Down