< prev index next >

src/hotspot/os/linux/os_perf_linux.cpp

Print this page




 189  *   params is the parameter number where the actual args to
 190  *       the format starts. If the args are in a va_list, this
 191  *       should be 0.
 192  */
 193 #ifndef PRINTF_ARGS
 194 #  define PRINTF_ARGS(formatSpec,  params) ATTRIBUTE_PRINTF(formatSpec, params)
 195 #endif
 196 
 197 #ifndef SCANF_ARGS
 198 #  define SCANF_ARGS(formatSpec,   params) ATTRIBUTE_SCANF(formatSpec, params)
 199 #endif
 200 
 201 #ifndef _PRINTFMT_
 202 #  define _PRINTFMT_
 203 #endif
 204 
 205 #ifndef _SCANFMT_
 206 #  define _SCANFMT_
 207 #endif
 208 







 209 typedef enum {
 210   CPU_LOAD_VM_ONLY,
 211   CPU_LOAD_GLOBAL,
 212 } CpuLoadTarget;
 213 
 214 enum {
 215   UNDETECTED,
 216   UNDETECTABLE,
 217   LINUX26_NPTL,
 218   BAREMETAL
 219 };
 220 
 221 struct CPUPerfCounters {
 222   int   nProcs;
 223   os::Linux::CPUPerfTicks jvmTicks;
 224   os::Linux::CPUPerfTicks* cpus;
 225 };
 226 
 227 static double get_cpu_load(int which_logical_cpu, CPUPerfCounters* counters, double* pkernelLoad, CpuLoadTarget target);
 228 
 229 /** reads /proc/<pid>/stat data, with some checks and some skips.
 230  *  Ensure that 'fmt' does _NOT_ contain the first two "%d %s"
 231  */
 232 static int SCANF_ARGS(2, 0) vread_statdata(const char* procfile, _SCANFMT_ const char* fmt, va_list args) {
 233   FILE*f;
 234   int n;
 235   char buf[2048];
 236 
 237   if ((f = fopen(procfile, "r")) == NULL) {
 238     return -1;
 239   }
 240 
 241   if ((n = fread(buf, 1, sizeof(buf), f)) != -1) {
 242     char *tmp;
 243 
 244     buf[n-1] = '\0';


 263   va_list args;
 264 
 265   va_start(args, fmt);
 266   n = vread_statdata(procfile, fmt, args);
 267   va_end(args);
 268   return n;
 269 }
 270 
 271 static FILE* open_statfile(void) {
 272   FILE *f;
 273 
 274   if ((f = fopen("/proc/stat", "r")) == NULL) {
 275     static int haveWarned = 0;
 276     if (!haveWarned) {
 277       haveWarned = 1;
 278     }
 279   }
 280   return f;
 281 }
 282 










































































 283 static int get_systemtype(void) {
 284   static int procEntriesType = UNDETECTED;
 285   DIR *taskDir;
 286 
 287   if (procEntriesType != UNDETECTED) {
 288     return procEntriesType;
 289   }
 290 
 291   // Check whether we have a task subdirectory
 292   if ((taskDir = opendir("/proc/self/task")) == NULL) {
 293     procEntriesType = UNDETECTABLE;
 294   } else {
 295     // The task subdirectory exists; we're on a Linux >= 2.6 system
 296     closedir(taskDir);
 297     procEntriesType = LINUX26_NPTL;
 298   }
 299 
 300   return procEntriesType;
 301 }
 302 
 303 /** read user and system ticks from a named procfile, assumed to be in 'stat' format then. */
 304 static int read_ticks(const char* procfile, uint64_t* userTicks, uint64_t* systemTicks) {
 305   return read_statdata(procfile, "%*c %*d %*d %*d %*d %*d %*u %*u %*u %*u %*u " UINT64_FORMAT " " UINT64_FORMAT,
 306     userTicks, systemTicks);
 307 }
 308 
 309 /**
 310  * Return the number of ticks spent in any of the processes belonging
 311  * to the JVM on any CPU.
 312  */
 313 static OSReturn get_jvm_ticks(os::Linux::CPUPerfTicks* pticks) {
 314   uint64_t userTicks;
 315   uint64_t systemTicks;
 316 
 317   if (get_systemtype() != LINUX26_NPTL) {
 318     return OS_ERR;
 319   }
 320 
 321   if (read_ticks("/proc/self/stat", &userTicks, &systemTicks) != 2) {
 322     return OS_ERR;
 323   }
 324 
 325   // get the total
 326   if (! os::Linux::get_tick_information(pticks, -1)) {
 327     return OS_ERR;
 328   }
 329 
 330   pticks->used       = userTicks;
 331   pticks->usedKernel = systemTicks;
 332 
 333   return OS_OK;
 334 }
 335 
 336 /**
 337  * Return the load of the CPU as a double. 1.0 means the CPU process uses all
 338  * available time for user or system processes, 0.0 means the CPU uses all time
 339  * being idle.
 340  *
 341  * Returns a negative value if there is a problem in determining the CPU load.
 342  */
 343 static double get_cpu_load(int which_logical_cpu, CPUPerfCounters* counters, double* pkernelLoad, CpuLoadTarget target) {
 344   uint64_t udiff, kdiff, tdiff;
 345   os::Linux::CPUPerfTicks* pticks;
 346   os::Linux::CPUPerfTicks  tmp;
 347   double user_load;
 348 
 349   *pkernelLoad = 0.0;
 350 
 351   if (target == CPU_LOAD_VM_ONLY) {
 352     pticks = &counters->jvmTicks;
 353   } else if (-1 == which_logical_cpu) {
 354     pticks = &counters->cpus[counters->nProcs];
 355   } else {
 356     pticks = &counters->cpus[which_logical_cpu];
 357   }
 358 
 359   tmp = *pticks;
 360 
 361   if (target == CPU_LOAD_VM_ONLY) {
 362     if (get_jvm_ticks(pticks) != OS_OK) {
 363       return -1.0;
 364     }
 365   } else if (! os::Linux::get_tick_information(pticks, which_logical_cpu)) {
 366     return -1.0;
 367   }
 368 
 369   // seems like we sometimes end up with less kernel ticks when
 370   // reading /proc/self/stat a second time, timing issue between cpus?
 371   if (pticks->usedKernel < tmp.usedKernel) {
 372     kdiff = 0;
 373   } else {
 374     kdiff = pticks->usedKernel - tmp.usedKernel;
 375   }
 376   tdiff = pticks->total - tmp.total;
 377   udiff = pticks->used - tmp.used;
 378 
 379   if (tdiff == 0) {
 380     return 0.0;
 381   } else if (tdiff < (udiff + kdiff)) {
 382     tdiff = udiff + kdiff;
 383   }
 384   *pkernelLoad = (kdiff / (double)tdiff);
 385   // BUG9044876, normalize return values to sane values


 486  private:
 487   CPUPerfCounters _counters;
 488 
 489   int cpu_load(int which_logical_cpu, double* cpu_load);
 490   int context_switch_rate(double* rate);
 491   int cpu_load_total_process(double* cpu_load);
 492   int cpu_loads_process(double* pjvmUserLoad, double* pjvmKernelLoad, double* psystemTotalLoad);
 493 
 494  public:
 495   CPUPerformance();
 496   bool initialize();
 497   ~CPUPerformance();
 498 };
 499 
 500 CPUPerformanceInterface::CPUPerformance::CPUPerformance() {
 501   _counters.nProcs = os::active_processor_count();
 502   _counters.cpus = NULL;
 503 }
 504 
 505 bool CPUPerformanceInterface::CPUPerformance::initialize() {
 506   size_t tick_array_size = (_counters.nProcs +1) * sizeof(os::Linux::CPUPerfTicks);
 507   _counters.cpus = (os::Linux::CPUPerfTicks*)NEW_C_HEAP_ARRAY(char, tick_array_size, mtInternal);
 508   if (NULL == _counters.cpus) {
 509     return false;
 510   }
 511   memset(_counters.cpus, 0, tick_array_size);
 512 
 513   // For the CPU load total
 514   os::Linux::get_tick_information(&_counters.cpus[_counters.nProcs], -1);
 515 
 516   // For each CPU
 517   for (int i = 0; i < _counters.nProcs; i++) {
 518     os::Linux::get_tick_information(&_counters.cpus[i], i);
 519   }
 520   // For JVM load
 521   get_jvm_ticks(&_counters.jvmTicks);
 522 
 523   // initialize context switch system
 524   // the double is only for init
 525   double init_ctx_switch_rate;
 526   perf_context_switch_rate(&init_ctx_switch_rate);
 527 
 528   return true;
 529 }
 530 
 531 CPUPerformanceInterface::CPUPerformance::~CPUPerformance() {
 532   if (_counters.cpus != NULL) {
 533     FREE_C_HEAP_ARRAY(char, _counters.cpus);
 534   }
 535 }
 536 
 537 int CPUPerformanceInterface::CPUPerformance::cpu_load(int which_logical_cpu, double* cpu_load) {
 538   double u, s;




 189  *   params is the parameter number where the actual args to
 190  *       the format starts. If the args are in a va_list, this
 191  *       should be 0.
 192  */
 193 #ifndef PRINTF_ARGS
 194 #  define PRINTF_ARGS(formatSpec,  params) ATTRIBUTE_PRINTF(formatSpec, params)
 195 #endif
 196 
 197 #ifndef SCANF_ARGS
 198 #  define SCANF_ARGS(formatSpec,   params) ATTRIBUTE_SCANF(formatSpec, params)
 199 #endif
 200 
 201 #ifndef _PRINTFMT_
 202 #  define _PRINTFMT_
 203 #endif
 204 
 205 #ifndef _SCANFMT_
 206 #  define _SCANFMT_
 207 #endif
 208 
 209 
 210 struct CPUPerfTicks {
 211   uint64_t  used;
 212   uint64_t  usedKernel;
 213   uint64_t  total;
 214 };
 215 
 216 typedef enum {
 217   CPU_LOAD_VM_ONLY,
 218   CPU_LOAD_GLOBAL,
 219 } CpuLoadTarget;
 220 
 221 enum {
 222   UNDETECTED,
 223   UNDETECTABLE,
 224   LINUX26_NPTL,
 225   BAREMETAL
 226 };
 227 
 228 struct CPUPerfCounters {
 229   int   nProcs;
 230   CPUPerfTicks jvmTicks;
 231   CPUPerfTicks* cpus;
 232 };
 233 
 234 static double get_cpu_load(int which_logical_cpu, CPUPerfCounters* counters, double* pkernelLoad, CpuLoadTarget target);
 235 
 236 /** reads /proc/<pid>/stat data, with some checks and some skips.
 237  *  Ensure that 'fmt' does _NOT_ contain the first two "%d %s"
 238  */
 239 static int SCANF_ARGS(2, 0) vread_statdata(const char* procfile, _SCANFMT_ const char* fmt, va_list args) {
 240   FILE*f;
 241   int n;
 242   char buf[2048];
 243 
 244   if ((f = fopen(procfile, "r")) == NULL) {
 245     return -1;
 246   }
 247 
 248   if ((n = fread(buf, 1, sizeof(buf), f)) != -1) {
 249     char *tmp;
 250 
 251     buf[n-1] = '\0';


 270   va_list args;
 271 
 272   va_start(args, fmt);
 273   n = vread_statdata(procfile, fmt, args);
 274   va_end(args);
 275   return n;
 276 }
 277 
 278 static FILE* open_statfile(void) {
 279   FILE *f;
 280 
 281   if ((f = fopen("/proc/stat", "r")) == NULL) {
 282     static int haveWarned = 0;
 283     if (!haveWarned) {
 284       haveWarned = 1;
 285     }
 286   }
 287   return f;
 288 }
 289 
 290 static void
 291 next_line(FILE *f) {
 292   int c;
 293   do {
 294     c = fgetc(f);
 295   } while (c != '\n' && c != EOF);
 296 }
 297 
 298 /**
 299  * Return the total number of ticks since the system was booted.
 300  * If the usedTicks parameter is not NULL, it will be filled with
 301  * the number of ticks spent on actual processes (user, system or
 302  * nice processes) since system boot. Note that this is the total number
 303  * of "executed" ticks on _all_ CPU:s, that is on a n-way system it is
 304  * n times the number of ticks that has passed in clock time.
 305  *
 306  * Returns a negative value if the reading of the ticks failed.
 307  */
 308 static OSReturn get_total_ticks(int which_logical_cpu, CPUPerfTicks* pticks) {
 309   FILE*         fh;
 310   uint64_t      userTicks, niceTicks, systemTicks, idleTicks;
 311   uint64_t      iowTicks = 0, irqTicks = 0, sirqTicks= 0;
 312   int           logical_cpu = -1;
 313   const int     expected_assign_count = (-1 == which_logical_cpu) ? 4 : 5;
 314   int           n;
 315 
 316   if ((fh = open_statfile()) == NULL) {
 317     return OS_ERR;
 318   }
 319   if (-1 == which_logical_cpu) {
 320     n = fscanf(fh, "cpu " UINT64_FORMAT " " UINT64_FORMAT " " UINT64_FORMAT " "
 321             UINT64_FORMAT " " UINT64_FORMAT " " UINT64_FORMAT " " UINT64_FORMAT,
 322             &userTicks, &niceTicks, &systemTicks, &idleTicks,
 323             &iowTicks, &irqTicks, &sirqTicks);
 324   } else {
 325     // Move to next line
 326     next_line(fh);
 327 
 328     // find the line for requested cpu faster to just iterate linefeeds?
 329     for (int i = 0; i < which_logical_cpu; i++) {
 330       next_line(fh);
 331     }
 332 
 333     n = fscanf(fh, "cpu%u " UINT64_FORMAT " " UINT64_FORMAT " " UINT64_FORMAT " "
 334                UINT64_FORMAT " " UINT64_FORMAT " " UINT64_FORMAT " " UINT64_FORMAT,
 335                &logical_cpu, &userTicks, &niceTicks,
 336                &systemTicks, &idleTicks, &iowTicks, &irqTicks, &sirqTicks);
 337   }
 338 
 339   fclose(fh);
 340   if (n < expected_assign_count || logical_cpu != which_logical_cpu) {
 341 #ifdef DEBUG_LINUX_PROC_STAT
 342     vm_fprintf(stderr, "[stat] read failed");
 343 #endif
 344     return OS_ERR;
 345   }
 346 
 347 #ifdef DEBUG_LINUX_PROC_STAT
 348   vm_fprintf(stderr, "[stat] read "
 349           UINT64_FORMAT " " UINT64_FORMAT " " UINT64_FORMAT " " UINT64_FORMAT " "
 350           UINT64_FORMAT " " UINT64_FORMAT " " UINT64_FORMAT " \n",
 351           userTicks, niceTicks, systemTicks, idleTicks,
 352           iowTicks, irqTicks, sirqTicks);
 353 #endif
 354 
 355   pticks->used       = userTicks + niceTicks;
 356   pticks->usedKernel = systemTicks + irqTicks + sirqTicks;
 357   pticks->total      = userTicks + niceTicks + systemTicks + idleTicks +
 358                        iowTicks + irqTicks + sirqTicks;
 359 
 360   return OS_OK;
 361 }
 362 
 363 
 364 static int get_systemtype(void) {
 365   static int procEntriesType = UNDETECTED;
 366   DIR *taskDir;
 367 
 368   if (procEntriesType != UNDETECTED) {
 369     return procEntriesType;
 370   }
 371 
 372   // Check whether we have a task subdirectory
 373   if ((taskDir = opendir("/proc/self/task")) == NULL) {
 374     procEntriesType = UNDETECTABLE;
 375   } else {
 376     // The task subdirectory exists; we're on a Linux >= 2.6 system
 377     closedir(taskDir);
 378     procEntriesType = LINUX26_NPTL;
 379   }
 380 
 381   return procEntriesType;
 382 }
 383 
 384 /** read user and system ticks from a named procfile, assumed to be in 'stat' format then. */
 385 static int read_ticks(const char* procfile, uint64_t* userTicks, uint64_t* systemTicks) {
 386   return read_statdata(procfile, "%*c %*d %*d %*d %*d %*d %*u %*u %*u %*u %*u " UINT64_FORMAT " " UINT64_FORMAT,
 387     userTicks, systemTicks);
 388 }
 389 
 390 /**
 391  * Return the number of ticks spent in any of the processes belonging
 392  * to the JVM on any CPU.
 393  */
 394 static OSReturn get_jvm_ticks(CPUPerfTicks* pticks) {
 395   uint64_t userTicks;
 396   uint64_t systemTicks;
 397 
 398   if (get_systemtype() != LINUX26_NPTL) {
 399     return OS_ERR;
 400   }
 401 
 402   if (read_ticks("/proc/self/stat", &userTicks, &systemTicks) != 2) {
 403     return OS_ERR;
 404   }
 405 
 406   // get the total
 407   if (get_total_ticks(-1, pticks) != OS_OK) {
 408     return OS_ERR;
 409   }
 410 
 411   pticks->used       = userTicks;
 412   pticks->usedKernel = systemTicks;
 413 
 414   return OS_OK;
 415 }
 416 
 417 /**
 418  * Return the load of the CPU as a double. 1.0 means the CPU process uses all
 419  * available time for user or system processes, 0.0 means the CPU uses all time
 420  * being idle.
 421  *
 422  * Returns a negative value if there is a problem in determining the CPU load.
 423  */
 424 static double get_cpu_load(int which_logical_cpu, CPUPerfCounters* counters, double* pkernelLoad, CpuLoadTarget target) {
 425   uint64_t udiff, kdiff, tdiff;
 426   CPUPerfTicks* pticks;
 427   CPUPerfTicks  tmp;
 428   double user_load;
 429 
 430   *pkernelLoad = 0.0;
 431 
 432   if (target == CPU_LOAD_VM_ONLY) {
 433     pticks = &counters->jvmTicks;
 434   } else if (-1 == which_logical_cpu) {
 435     pticks = &counters->cpus[counters->nProcs];
 436   } else {
 437     pticks = &counters->cpus[which_logical_cpu];
 438   }
 439 
 440   tmp = *pticks;
 441 
 442   if (target == CPU_LOAD_VM_ONLY) {
 443     if (get_jvm_ticks(pticks) != OS_OK) {
 444       return -1.0;
 445     }
 446   } else if (get_total_ticks(which_logical_cpu, pticks) != OS_OK) {
 447     return -1.0;
 448   }
 449 
 450   // seems like we sometimes end up with less kernel ticks when
 451   // reading /proc/self/stat a second time, timing issue between cpus?
 452   if (pticks->usedKernel < tmp.usedKernel) {
 453     kdiff = 0;
 454   } else {
 455     kdiff = pticks->usedKernel - tmp.usedKernel;
 456   }
 457   tdiff = pticks->total - tmp.total;
 458   udiff = pticks->used - tmp.used;
 459 
 460   if (tdiff == 0) {
 461     return 0.0;
 462   } else if (tdiff < (udiff + kdiff)) {
 463     tdiff = udiff + kdiff;
 464   }
 465   *pkernelLoad = (kdiff / (double)tdiff);
 466   // BUG9044876, normalize return values to sane values


 567  private:
 568   CPUPerfCounters _counters;
 569 
 570   int cpu_load(int which_logical_cpu, double* cpu_load);
 571   int context_switch_rate(double* rate);
 572   int cpu_load_total_process(double* cpu_load);
 573   int cpu_loads_process(double* pjvmUserLoad, double* pjvmKernelLoad, double* psystemTotalLoad);
 574 
 575  public:
 576   CPUPerformance();
 577   bool initialize();
 578   ~CPUPerformance();
 579 };
 580 
 581 CPUPerformanceInterface::CPUPerformance::CPUPerformance() {
 582   _counters.nProcs = os::active_processor_count();
 583   _counters.cpus = NULL;
 584 }
 585 
 586 bool CPUPerformanceInterface::CPUPerformance::initialize() {
 587   size_t tick_array_size = (_counters.nProcs +1) * sizeof(CPUPerfTicks);
 588   _counters.cpus = (CPUPerfTicks*)NEW_C_HEAP_ARRAY(char, tick_array_size, mtInternal);
 589   if (NULL == _counters.cpus) {
 590     return false;
 591   }
 592   memset(_counters.cpus, 0, tick_array_size);
 593 
 594   // For the CPU load total
 595   get_total_ticks(-1, &_counters.cpus[_counters.nProcs]);
 596 
 597   // For each CPU
 598   for (int i = 0; i < _counters.nProcs; i++) {
 599     get_total_ticks(i, &_counters.cpus[i]);
 600   }
 601   // For JVM load
 602   get_jvm_ticks(&_counters.jvmTicks);
 603 
 604   // initialize context switch system
 605   // the double is only for init
 606   double init_ctx_switch_rate;
 607   perf_context_switch_rate(&init_ctx_switch_rate);
 608 
 609   return true;
 610 }
 611 
 612 CPUPerformanceInterface::CPUPerformance::~CPUPerformance() {
 613   if (_counters.cpus != NULL) {
 614     FREE_C_HEAP_ARRAY(char, _counters.cpus);
 615   }
 616 }
 617 
 618 int CPUPerformanceInterface::CPUPerformance::cpu_load(int which_logical_cpu, double* cpu_load) {
 619   double u, s;


< prev index next >