8221535: add steal tick related information to hs_error file [linux]
Reviewed-by: dholmes, goetz
--- a/src/hotspot/os/aix/os_perf_aix.cpp Mon Apr 08 21:39:43 2019 +0000
+++ b/src/hotspot/os/aix/os_perf_aix.cpp Mon Apr 08 14:36:33 2019 +0200
@@ -336,20 +336,8 @@
fclose(fh);
if (n < expected_assign_count || logical_cpu != which_logical_cpu) {
-#ifdef DEBUG_LINUX_PROC_STAT
- vm_fprintf(stderr, "[stat] read failed");
-#endif
return OS_ERR;
}
-
-#ifdef DEBUG_LINUX_PROC_STAT
- vm_fprintf(stderr, "[stat] read "
- UINT64_FORMAT " " UINT64_FORMAT " " UINT64_FORMAT " " UINT64_FORMAT " "
- UINT64_FORMAT " " UINT64_FORMAT " " UINT64_FORMAT " \n",
- userTicks, niceTicks, systemTicks, idleTicks,
- iowTicks, irqTicks, sirqTicks);
-#endif
-
pticks->used = userTicks + niceTicks;
pticks->usedKernel = systemTicks + irqTicks + sirqTicks;
pticks->total = userTicks + niceTicks + systemTicks + idleTicks +
--- a/src/hotspot/os/linux/os_linux.cpp Mon Apr 08 21:39:43 2019 +0000
+++ b/src/hotspot/os/linux/os_linux.cpp Mon Apr 08 14:36:33 2019 +0200
@@ -227,6 +227,82 @@
return phys_mem;
}
+static uint64_t initial_total_ticks = 0;
+static uint64_t initial_steal_ticks = 0;
+static bool has_initial_tick_info = false;
+
+static void next_line(FILE *f) {
+ int c;
+ do {
+ c = fgetc(f);
+ } while (c != '\n' && c != EOF);
+}
+
+bool os::Linux::get_tick_information(CPUPerfTicks* pticks, int which_logical_cpu) {
+ FILE* fh;
+ uint64_t userTicks, niceTicks, systemTicks, idleTicks;
+ // since at least kernel 2.6 : iowait: time waiting for I/O to complete
+ // irq: time servicing interrupts; softirq: time servicing softirqs
+ uint64_t iowTicks = 0, irqTicks = 0, sirqTicks= 0;
+ // steal (since kernel 2.6.11): time spent in other OS when running in a virtualized environment
+ uint64_t stealTicks = 0;
+ // guest (since kernel 2.6.24): time spent running a virtual CPU for guest OS under the
+ // control of the Linux kernel
+ uint64_t guestNiceTicks = 0;
+ int logical_cpu = -1;
+ const int required_tickinfo_count = (which_logical_cpu == -1) ? 4 : 5;
+ int n;
+
+ memset(pticks, 0, sizeof(CPUPerfTicks));
+
+ if ((fh = fopen("/proc/stat", "r")) == NULL) {
+ return false;
+ }
+
+ if (which_logical_cpu == -1) {
+ n = fscanf(fh, "cpu " UINT64_FORMAT " " UINT64_FORMAT " " UINT64_FORMAT " "
+ UINT64_FORMAT " " UINT64_FORMAT " " UINT64_FORMAT " " UINT64_FORMAT " "
+ UINT64_FORMAT " " UINT64_FORMAT " ",
+ &userTicks, &niceTicks, &systemTicks, &idleTicks,
+ &iowTicks, &irqTicks, &sirqTicks,
+ &stealTicks, &guestNiceTicks);
+ } else {
+ // Move to next line
+ next_line(fh);
+
+ // find the line for requested cpu faster to just iterate linefeeds?
+ for (int i = 0; i < which_logical_cpu; i++) {
+ next_line(fh);
+ }
+
+ n = fscanf(fh, "cpu%u " UINT64_FORMAT " " UINT64_FORMAT " " UINT64_FORMAT " "
+ UINT64_FORMAT " " UINT64_FORMAT " " UINT64_FORMAT " " UINT64_FORMAT " "
+ UINT64_FORMAT " " UINT64_FORMAT " ",
+ &logical_cpu, &userTicks, &niceTicks,
+ &systemTicks, &idleTicks, &iowTicks, &irqTicks, &sirqTicks,
+ &stealTicks, &guestNiceTicks);
+ }
+
+ fclose(fh);
+ if (n < required_tickinfo_count || logical_cpu != which_logical_cpu) {
+ return false;
+ }
+ pticks->used = userTicks + niceTicks;
+ pticks->usedKernel = systemTicks + irqTicks + sirqTicks;
+ pticks->total = userTicks + niceTicks + systemTicks + idleTicks +
+ iowTicks + irqTicks + sirqTicks + stealTicks + guestNiceTicks;
+
+ if (n > required_tickinfo_count + 3) {
+ pticks->steal = stealTicks;
+ pticks->has_steal_ticks = true;
+ } else {
+ pticks->steal = 0;
+ pticks->has_steal_ticks = false;
+ }
+
+ return true;
+}
+
// Return true if user is running as root.
bool os::have_special_privileges() {
@@ -1977,6 +2053,8 @@
os::Linux::print_container_info(st);
os::Linux::print_virtualization_info(st);
+
+ os::Linux::print_steal_info(st);
}
// Try to identify popular distros.
@@ -2265,6 +2343,24 @@
#endif
}
+void os::Linux::print_steal_info(outputStream* st) {
+ if (has_initial_tick_info) {
+ CPUPerfTicks pticks;
+ bool res = os::Linux::get_tick_information(&pticks, -1);
+
+ if (res && pticks.has_steal_ticks) {
+ uint64_t steal_ticks_difference = pticks.steal - initial_steal_ticks;
+ uint64_t total_ticks_difference = pticks.total - initial_total_ticks;
+ double steal_ticks_perc = 0.0;
+ if (total_ticks_difference != 0) {
+ steal_ticks_perc = (double) steal_ticks_difference / total_ticks_difference;
+ }
+ st->print_cr("Steal ticks since vm start: " UINT64_FORMAT, steal_ticks_difference);
+ st->print_cr("Steal ticks percentage since vm start:%7.3f", steal_ticks_perc);
+ }
+ }
+}
+
void os::print_memory_info(outputStream* st) {
st->print("Memory:");
@@ -4989,6 +5085,15 @@
Linux::initialize_os_info();
+ os::Linux::CPUPerfTicks pticks;
+ bool res = os::Linux::get_tick_information(&pticks, -1);
+
+ if (res && pticks.has_steal_ticks) {
+ has_initial_tick_info = true;
+ initial_total_ticks = pticks.total;
+ initial_steal_ticks = pticks.steal;
+ }
+
// _main_thread points to the thread that created/loaded the JVM.
Linux::_main_thread = pthread_self();
--- a/src/hotspot/os/linux/os_linux.hpp Mon Apr 08 21:39:43 2019 +0000
+++ b/src/hotspot/os/linux/os_linux.hpp Mon Apr 08 14:36:33 2019 +0200
@@ -109,12 +109,23 @@
static void print_full_memory_info(outputStream* st);
static void print_container_info(outputStream* st);
static void print_virtualization_info(outputStream* st);
+ static void print_steal_info(outputStream* st);
static void print_distro_info(outputStream* st);
static void print_libversion_info(outputStream* st);
static void print_proc_sys_info(outputStream* st);
static void print_ld_preload_file(outputStream* st);
public:
+ struct CPUPerfTicks {
+ uint64_t used;
+ uint64_t usedKernel;
+ uint64_t total;
+ uint64_t steal;
+ bool has_steal_ticks;
+ };
+
+ // which_logical_cpu=-1 returns accumulated ticks for all cpus.
+ static bool get_tick_information(CPUPerfTicks* pticks, int which_logical_cpu);
static bool _stack_is_executable;
static void *dlopen_helper(const char *name, char *ebuf, int ebuflen);
static void *dll_load_in_vmthread(const char *name, char *ebuf, int ebuflen);
--- a/src/hotspot/os/linux/os_perf_linux.cpp Mon Apr 08 21:39:43 2019 +0000
+++ b/src/hotspot/os/linux/os_perf_linux.cpp Mon Apr 08 14:36:33 2019 +0200
@@ -206,13 +206,6 @@
# define _SCANFMT_
#endif
-
-struct CPUPerfTicks {
- uint64_t used;
- uint64_t usedKernel;
- uint64_t total;
-};
-
typedef enum {
CPU_LOAD_VM_ONLY,
CPU_LOAD_GLOBAL,
@@ -227,8 +220,8 @@
struct CPUPerfCounters {
int nProcs;
- CPUPerfTicks jvmTicks;
- CPUPerfTicks* cpus;
+ os::Linux::CPUPerfTicks jvmTicks;
+ os::Linux::CPUPerfTicks* cpus;
};
static double get_cpu_load(int which_logical_cpu, CPUPerfCounters* counters, double* pkernelLoad, CpuLoadTarget target);
@@ -287,80 +280,6 @@
return f;
}
-static void
-next_line(FILE *f) {
- int c;
- do {
- c = fgetc(f);
- } while (c != '\n' && c != EOF);
-}
-
-/**
- * Return the total number of ticks since the system was booted.
- * If the usedTicks parameter is not NULL, it will be filled with
- * the number of ticks spent on actual processes (user, system or
- * nice processes) since system boot. Note that this is the total number
- * of "executed" ticks on _all_ CPU:s, that is on a n-way system it is
- * n times the number of ticks that has passed in clock time.
- *
- * Returns a negative value if the reading of the ticks failed.
- */
-static OSReturn get_total_ticks(int which_logical_cpu, CPUPerfTicks* pticks) {
- FILE* fh;
- uint64_t userTicks, niceTicks, systemTicks, idleTicks;
- uint64_t iowTicks = 0, irqTicks = 0, sirqTicks= 0;
- int logical_cpu = -1;
- const int expected_assign_count = (-1 == which_logical_cpu) ? 4 : 5;
- int n;
-
- if ((fh = open_statfile()) == NULL) {
- return OS_ERR;
- }
- if (-1 == which_logical_cpu) {
- n = fscanf(fh, "cpu " UINT64_FORMAT " " UINT64_FORMAT " " UINT64_FORMAT " "
- UINT64_FORMAT " " UINT64_FORMAT " " UINT64_FORMAT " " UINT64_FORMAT,
- &userTicks, &niceTicks, &systemTicks, &idleTicks,
- &iowTicks, &irqTicks, &sirqTicks);
- } else {
- // Move to next line
- next_line(fh);
-
- // find the line for requested cpu faster to just iterate linefeeds?
- for (int i = 0; i < which_logical_cpu; i++) {
- next_line(fh);
- }
-
- n = fscanf(fh, "cpu%u " UINT64_FORMAT " " UINT64_FORMAT " " UINT64_FORMAT " "
- UINT64_FORMAT " " UINT64_FORMAT " " UINT64_FORMAT " " UINT64_FORMAT,
- &logical_cpu, &userTicks, &niceTicks,
- &systemTicks, &idleTicks, &iowTicks, &irqTicks, &sirqTicks);
- }
-
- fclose(fh);
- if (n < expected_assign_count || logical_cpu != which_logical_cpu) {
-#ifdef DEBUG_LINUX_PROC_STAT
- vm_fprintf(stderr, "[stat] read failed");
-#endif
- return OS_ERR;
- }
-
-#ifdef DEBUG_LINUX_PROC_STAT
- vm_fprintf(stderr, "[stat] read "
- UINT64_FORMAT " " UINT64_FORMAT " " UINT64_FORMAT " " UINT64_FORMAT " "
- UINT64_FORMAT " " UINT64_FORMAT " " UINT64_FORMAT " \n",
- userTicks, niceTicks, systemTicks, idleTicks,
- iowTicks, irqTicks, sirqTicks);
-#endif
-
- pticks->used = userTicks + niceTicks;
- pticks->usedKernel = systemTicks + irqTicks + sirqTicks;
- pticks->total = userTicks + niceTicks + systemTicks + idleTicks +
- iowTicks + irqTicks + sirqTicks;
-
- return OS_OK;
-}
-
-
static int get_systemtype(void) {
static int procEntriesType = UNDETECTED;
DIR *taskDir;
@@ -391,7 +310,7 @@
* Return the number of ticks spent in any of the processes belonging
* to the JVM on any CPU.
*/
-static OSReturn get_jvm_ticks(CPUPerfTicks* pticks) {
+static OSReturn get_jvm_ticks(os::Linux::CPUPerfTicks* pticks) {
uint64_t userTicks;
uint64_t systemTicks;
@@ -404,7 +323,7 @@
}
// get the total
- if (get_total_ticks(-1, pticks) != OS_OK) {
+ if (! os::Linux::get_tick_information(pticks, -1)) {
return OS_ERR;
}
@@ -423,8 +342,8 @@
*/
static double get_cpu_load(int which_logical_cpu, CPUPerfCounters* counters, double* pkernelLoad, CpuLoadTarget target) {
uint64_t udiff, kdiff, tdiff;
- CPUPerfTicks* pticks;
- CPUPerfTicks tmp;
+ os::Linux::CPUPerfTicks* pticks;
+ os::Linux::CPUPerfTicks tmp;
double user_load;
*pkernelLoad = 0.0;
@@ -443,7 +362,7 @@
if (get_jvm_ticks(pticks) != OS_OK) {
return -1.0;
}
- } else if (get_total_ticks(which_logical_cpu, pticks) != OS_OK) {
+ } else if (! os::Linux::get_tick_information(pticks, which_logical_cpu)) {
return -1.0;
}
@@ -584,19 +503,19 @@
}
bool CPUPerformanceInterface::CPUPerformance::initialize() {
- size_t tick_array_size = (_counters.nProcs +1) * sizeof(CPUPerfTicks);
- _counters.cpus = (CPUPerfTicks*)NEW_C_HEAP_ARRAY(char, tick_array_size, mtInternal);
+ size_t tick_array_size = (_counters.nProcs +1) * sizeof(os::Linux::CPUPerfTicks);
+ _counters.cpus = (os::Linux::CPUPerfTicks*)NEW_C_HEAP_ARRAY(char, tick_array_size, mtInternal);
if (NULL == _counters.cpus) {
return false;
}
memset(_counters.cpus, 0, tick_array_size);
// For the CPU load total
- get_total_ticks(-1, &_counters.cpus[_counters.nProcs]);
+ os::Linux::get_tick_information(&_counters.cpus[_counters.nProcs], -1);
// For each CPU
for (int i = 0; i < _counters.nProcs; i++) {
- get_total_ticks(i, &_counters.cpus[i]);
+ os::Linux::get_tick_information(&_counters.cpus[i], i);
}
// For JVM load
get_jvm_ticks(&_counters.jvmTicks);