mirror of
https://github.com/openjdk/jdk.git
synced 2025-09-17 17:44:40 +02:00
8221535: add steal tick related information to hs_error file [linux]
Reviewed-by: dholmes, goetz
This commit is contained in:
parent
3ca21234ce
commit
8f556345e1
4 changed files with 127 additions and 104 deletions
|
@ -336,20 +336,8 @@ static OSReturn get_total_ticks(int which_logical_cpu, CPUPerfTicks* pticks) {
|
||||||
|
|
||||||
fclose(fh);
|
fclose(fh);
|
||||||
if (n < expected_assign_count || logical_cpu != which_logical_cpu) {
|
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;
|
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->used = userTicks + niceTicks;
|
||||||
pticks->usedKernel = systemTicks + irqTicks + sirqTicks;
|
pticks->usedKernel = systemTicks + irqTicks + sirqTicks;
|
||||||
pticks->total = userTicks + niceTicks + systemTicks + idleTicks +
|
pticks->total = userTicks + niceTicks + systemTicks + idleTicks +
|
||||||
|
|
|
@ -227,6 +227,82 @@ julong os::physical_memory() {
|
||||||
return phys_mem;
|
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.
|
// Return true if user is running as root.
|
||||||
|
|
||||||
bool os::have_special_privileges() {
|
bool os::have_special_privileges() {
|
||||||
|
@ -1977,6 +2053,8 @@ void os::print_os_info(outputStream* st) {
|
||||||
os::Linux::print_container_info(st);
|
os::Linux::print_container_info(st);
|
||||||
|
|
||||||
os::Linux::print_virtualization_info(st);
|
os::Linux::print_virtualization_info(st);
|
||||||
|
|
||||||
|
os::Linux::print_steal_info(st);
|
||||||
}
|
}
|
||||||
|
|
||||||
// Try to identify popular distros.
|
// Try to identify popular distros.
|
||||||
|
@ -2265,6 +2343,24 @@ void os::Linux::print_virtualization_info(outputStream* st) {
|
||||||
#endif
|
#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) {
|
void os::print_memory_info(outputStream* st) {
|
||||||
|
|
||||||
st->print("Memory:");
|
st->print("Memory:");
|
||||||
|
@ -4989,6 +5085,15 @@ void os::init(void) {
|
||||||
|
|
||||||
Linux::initialize_os_info();
|
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.
|
// _main_thread points to the thread that created/loaded the JVM.
|
||||||
Linux::_main_thread = pthread_self();
|
Linux::_main_thread = pthread_self();
|
||||||
|
|
||||||
|
|
|
@ -109,12 +109,23 @@ class Linux {
|
||||||
static void print_full_memory_info(outputStream* st);
|
static void print_full_memory_info(outputStream* st);
|
||||||
static void print_container_info(outputStream* st);
|
static void print_container_info(outputStream* st);
|
||||||
static void print_virtualization_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_distro_info(outputStream* st);
|
||||||
static void print_libversion_info(outputStream* st);
|
static void print_libversion_info(outputStream* st);
|
||||||
static void print_proc_sys_info(outputStream* st);
|
static void print_proc_sys_info(outputStream* st);
|
||||||
static void print_ld_preload_file(outputStream* st);
|
static void print_ld_preload_file(outputStream* st);
|
||||||
|
|
||||||
public:
|
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 bool _stack_is_executable;
|
||||||
static void *dlopen_helper(const char *name, char *ebuf, int ebuflen);
|
static void *dlopen_helper(const char *name, char *ebuf, int ebuflen);
|
||||||
static void *dll_load_in_vmthread(const char *name, char *ebuf, int ebuflen);
|
static void *dll_load_in_vmthread(const char *name, char *ebuf, int ebuflen);
|
||||||
|
|
|
@ -206,13 +206,6 @@ format: %d %s %c %d %d %d %d %d %lu %lu %lu %lu %lu %lu %lu %ld %ld %ld %l
|
||||||
# define _SCANFMT_
|
# define _SCANFMT_
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
|
|
||||||
struct CPUPerfTicks {
|
|
||||||
uint64_t used;
|
|
||||||
uint64_t usedKernel;
|
|
||||||
uint64_t total;
|
|
||||||
};
|
|
||||||
|
|
||||||
typedef enum {
|
typedef enum {
|
||||||
CPU_LOAD_VM_ONLY,
|
CPU_LOAD_VM_ONLY,
|
||||||
CPU_LOAD_GLOBAL,
|
CPU_LOAD_GLOBAL,
|
||||||
|
@ -227,8 +220,8 @@ enum {
|
||||||
|
|
||||||
struct CPUPerfCounters {
|
struct CPUPerfCounters {
|
||||||
int nProcs;
|
int nProcs;
|
||||||
CPUPerfTicks jvmTicks;
|
os::Linux::CPUPerfTicks jvmTicks;
|
||||||
CPUPerfTicks* cpus;
|
os::Linux::CPUPerfTicks* cpus;
|
||||||
};
|
};
|
||||||
|
|
||||||
static double get_cpu_load(int which_logical_cpu, CPUPerfCounters* counters, double* pkernelLoad, CpuLoadTarget target);
|
static double get_cpu_load(int which_logical_cpu, CPUPerfCounters* counters, double* pkernelLoad, CpuLoadTarget target);
|
||||||
|
@ -287,80 +280,6 @@ static FILE* open_statfile(void) {
|
||||||
return f;
|
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 get_systemtype(void) {
|
||||||
static int procEntriesType = UNDETECTED;
|
static int procEntriesType = UNDETECTED;
|
||||||
DIR *taskDir;
|
DIR *taskDir;
|
||||||
|
@ -391,7 +310,7 @@ static int read_ticks(const char* procfile, uint64_t* userTicks, uint64_t* syste
|
||||||
* Return the number of ticks spent in any of the processes belonging
|
* Return the number of ticks spent in any of the processes belonging
|
||||||
* to the JVM on any CPU.
|
* 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 userTicks;
|
||||||
uint64_t systemTicks;
|
uint64_t systemTicks;
|
||||||
|
|
||||||
|
@ -404,7 +323,7 @@ static OSReturn get_jvm_ticks(CPUPerfTicks* pticks) {
|
||||||
}
|
}
|
||||||
|
|
||||||
// get the total
|
// get the total
|
||||||
if (get_total_ticks(-1, pticks) != OS_OK) {
|
if (! os::Linux::get_tick_information(pticks, -1)) {
|
||||||
return OS_ERR;
|
return OS_ERR;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -423,8 +342,8 @@ static OSReturn get_jvm_ticks(CPUPerfTicks* pticks) {
|
||||||
*/
|
*/
|
||||||
static double get_cpu_load(int which_logical_cpu, CPUPerfCounters* counters, double* pkernelLoad, CpuLoadTarget target) {
|
static double get_cpu_load(int which_logical_cpu, CPUPerfCounters* counters, double* pkernelLoad, CpuLoadTarget target) {
|
||||||
uint64_t udiff, kdiff, tdiff;
|
uint64_t udiff, kdiff, tdiff;
|
||||||
CPUPerfTicks* pticks;
|
os::Linux::CPUPerfTicks* pticks;
|
||||||
CPUPerfTicks tmp;
|
os::Linux::CPUPerfTicks tmp;
|
||||||
double user_load;
|
double user_load;
|
||||||
|
|
||||||
*pkernelLoad = 0.0;
|
*pkernelLoad = 0.0;
|
||||||
|
@ -443,7 +362,7 @@ static double get_cpu_load(int which_logical_cpu, CPUPerfCounters* counters, dou
|
||||||
if (get_jvm_ticks(pticks) != OS_OK) {
|
if (get_jvm_ticks(pticks) != OS_OK) {
|
||||||
return -1.0;
|
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;
|
return -1.0;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -584,19 +503,19 @@ CPUPerformanceInterface::CPUPerformance::CPUPerformance() {
|
||||||
}
|
}
|
||||||
|
|
||||||
bool CPUPerformanceInterface::CPUPerformance::initialize() {
|
bool CPUPerformanceInterface::CPUPerformance::initialize() {
|
||||||
size_t tick_array_size = (_counters.nProcs +1) * sizeof(CPUPerfTicks);
|
size_t tick_array_size = (_counters.nProcs +1) * sizeof(os::Linux::CPUPerfTicks);
|
||||||
_counters.cpus = (CPUPerfTicks*)NEW_C_HEAP_ARRAY(char, tick_array_size, mtInternal);
|
_counters.cpus = (os::Linux::CPUPerfTicks*)NEW_C_HEAP_ARRAY(char, tick_array_size, mtInternal);
|
||||||
if (NULL == _counters.cpus) {
|
if (NULL == _counters.cpus) {
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
memset(_counters.cpus, 0, tick_array_size);
|
memset(_counters.cpus, 0, tick_array_size);
|
||||||
|
|
||||||
// For the CPU load total
|
// 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 each CPU
|
||||||
for (int i = 0; i < _counters.nProcs; i++) {
|
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
|
// For JVM load
|
||||||
get_jvm_ticks(&_counters.jvmTicks);
|
get_jvm_ticks(&_counters.jvmTicks);
|
||||||
|
|
Loading…
Add table
Add a link
Reference in a new issue