src/os/bsd/vm/os_perf_bsd.cpp

Mon, 12 Aug 2019 18:30:40 +0300

author
apetushkov
date
Mon, 12 Aug 2019 18:30:40 +0300
changeset 9858
b985cbb00e68
permissions
-rw-r--r--

8223147: JFR Backport
8199712: Flight Recorder
8203346: JFR: Inconsistent signature of jfr_add_string_constant
8195817: JFR.stop should require name of recording
8195818: JFR.start should increase autogenerated name by one
8195819: Remove recording=x from jcmd JFR.check output
8203921: JFR thread sampling is missing fixes from JDK-8194552
8203929: Limit amount of data for JFR.dump
8203664: JFR start failure after AppCDS archive created with JFR StartFlightRecording
8003209: JFR events for network utilization
8207392: [PPC64] Implement JFR profiling
8202835: jfr/event/os/TestSystemProcess.java fails on missing events
Summary: Backport JFR from JDK11. Initial integration
Reviewed-by: neugens

     1 /*
     2  * Copyright (c) 2012, 2018, Oracle and/or its affiliates. All rights reserved.
     3  * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
     4  *
     5  * This code is free software; you can redistribute it and/or modify it
     6  * under the terms of the GNU General Public License version 2 only, as
     7  * published by the Free Software Foundation.
     8  *
     9  * This code is distributed in the hope that it will be useful, but WITHOUT
    10  * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
    11  * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
    12  * version 2 for more details (a copy is included in the LICENSE file that
    13  * accompanied this code).
    14  *
    15  * You should have received a copy of the GNU General Public License version
    16  * 2 along with this work; if not, write to the Free Software Foundation,
    17  * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
    18  *
    19  * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
    20  * or visit www.oracle.com if you need additional information or have any
    21  * questions.
    22  *
    23  */
    24 #include "precompiled.hpp"
    25 #include "memory/allocation.inline.hpp"
    26 #include "memory/resourceArea.hpp"
    27 #include "runtime/os.hpp"
    28 #include "runtime/os_perf.hpp"
    29 #include "vm_version_ext_x86.hpp"
    31 #ifdef __APPLE__
    32   #import <libproc.h>
    33   #include <sys/time.h>
    34   #include <sys/sysctl.h>
    35   #include <mach/mach.h>
    36   #include <mach/task_info.h>
    37   #include <sys/socket.h>
    38   #include <net/if.h>
    39   #include <net/if_dl.h>
    40   #include <net/route.h>
    41 #endif
    43 static const double NANOS_PER_SEC = 1000000000.0;
    45 class CPUPerformanceInterface::CPUPerformance : public CHeapObj<mtInternal> {
    46    friend class CPUPerformanceInterface;
    47  private:
    48   long _total_cpu_nanos;
    49   long _total_csr_nanos;
    50   long _jvm_user_nanos;
    51   long _jvm_system_nanos;
    52   long _jvm_context_switches;
    53   long _used_ticks;
    54   long _total_ticks;
    55   int  _active_processor_count;
    57   bool now_in_nanos(long* resultp) {
    58     timeval current_time;
    59     if (gettimeofday(&current_time, NULL) != 0) {
    60       // Error getting current time
    61       return false;
    62     }
    63     *resultp = (long)(current_time.tv_sec * NANOS_PER_SEC + 1000L * current_time.tv_usec);
    64     return true;
    65   }
    67   double normalize(double value) {
    68     return MIN2<double>(MAX2<double>(value, 0.0), 1.0);
    69   }
    70   int cpu_load(int which_logical_cpu, double* cpu_load);
    71   int context_switch_rate(double* rate);
    72   int cpu_load_total_process(double* cpu_load);
    73   int cpu_loads_process(double* pjvmUserLoad, double* pjvmKernelLoad, double* psystemTotalLoad);
    75   CPUPerformance(const CPUPerformance& rhs); // no impl
    76   CPUPerformance& operator=(const CPUPerformance& rhs); // no impl
    77  public:
    78   CPUPerformance();
    79   bool initialize();
    80   ~CPUPerformance();
    81 };
    83 CPUPerformanceInterface::CPUPerformance::CPUPerformance() {
    84   _total_cpu_nanos= 0;
    85   _total_csr_nanos= 0;
    86   _jvm_context_switches = 0;
    87   _jvm_user_nanos = 0;
    88   _jvm_system_nanos = 0;
    89   _used_ticks = 0;
    90   _total_ticks = 0;
    91   _active_processor_count = 0;
    92 }
    94 bool CPUPerformanceInterface::CPUPerformance::initialize() {
    95   return true;
    96 }
    98 CPUPerformanceInterface::CPUPerformance::~CPUPerformance() {
    99 }
   101 int CPUPerformanceInterface::CPUPerformance::cpu_load(int which_logical_cpu, double* cpu_load) {
   102   return FUNCTIONALITY_NOT_IMPLEMENTED;
   103 }
   105 int CPUPerformanceInterface::CPUPerformance::cpu_load_total_process(double* cpu_load) {
   106 #ifdef __APPLE__
   107   host_name_port_t host = mach_host_self();
   108   host_flavor_t flavor = HOST_CPU_LOAD_INFO;
   109   mach_msg_type_number_t host_info_count = HOST_CPU_LOAD_INFO_COUNT;
   110   host_cpu_load_info_data_t cpu_load_info;
   112   kern_return_t kr = host_statistics(host, flavor, (host_info_t)&cpu_load_info, &host_info_count);
   113   if (kr != KERN_SUCCESS) {
   114     return OS_ERR;
   115   }
   117   long used_ticks  = cpu_load_info.cpu_ticks[CPU_STATE_USER] + cpu_load_info.cpu_ticks[CPU_STATE_NICE] + cpu_load_info.cpu_ticks[CPU_STATE_SYSTEM];
   118   long total_ticks = used_ticks + cpu_load_info.cpu_ticks[CPU_STATE_IDLE];
   120   if (_used_ticks == 0 || _total_ticks == 0) {
   121     // First call, just set the values
   122     _used_ticks  = used_ticks;
   123     _total_ticks = total_ticks;
   124     return OS_ERR;
   125   }
   127   long used_delta  = used_ticks - _used_ticks;
   128   long total_delta = total_ticks - _total_ticks;
   130   _used_ticks  = used_ticks;
   131   _total_ticks = total_ticks;
   133   if (total_delta == 0) {
   134     // Avoid division by zero
   135     return OS_ERR;
   136   }
   138   *cpu_load = (double)used_delta / total_delta;
   140   return OS_OK;
   141 #else
   142   return FUNCTIONALITY_NOT_IMPLEMENTED;
   143 #endif
   144 }
   146 int CPUPerformanceInterface::CPUPerformance::cpu_loads_process(double* pjvmUserLoad, double* pjvmKernelLoad, double* psystemTotalLoad) {
   147 #ifdef __APPLE__
   148   int result = cpu_load_total_process(psystemTotalLoad);
   149   mach_port_t task = mach_task_self();
   150   mach_msg_type_number_t task_info_count = TASK_INFO_MAX;
   151   task_info_data_t task_info_data;
   152   kern_return_t kr = task_info(task, TASK_ABSOLUTETIME_INFO, (task_info_t)task_info_data, &task_info_count);
   153   if (kr != KERN_SUCCESS) {
   154     return OS_ERR;
   155   }
   156   task_absolutetime_info_t absolutetime_info = (task_absolutetime_info_t)task_info_data;
   158   int active_processor_count = os::active_processor_count();
   159   long jvm_user_nanos = absolutetime_info->total_user;
   160   long jvm_system_nanos = absolutetime_info->total_system;
   162   long total_cpu_nanos;
   163   if(!now_in_nanos(&total_cpu_nanos)) {
   164     return OS_ERR;
   165   }
   167   if (_total_cpu_nanos == 0 || active_processor_count != _active_processor_count) {
   168     // First call or change in active processor count
   169     result = OS_ERR;
   170   }
   172   long delta_nanos = active_processor_count * (total_cpu_nanos - _total_cpu_nanos);
   173   if (delta_nanos == 0) {
   174     // Avoid division by zero
   175     return OS_ERR;
   176   }
   178   *pjvmUserLoad = normalize((double)(jvm_user_nanos - _jvm_user_nanos)/delta_nanos);
   179   *pjvmKernelLoad = normalize((double)(jvm_system_nanos - _jvm_system_nanos)/delta_nanos);
   181   _active_processor_count = active_processor_count;
   182   _total_cpu_nanos = total_cpu_nanos;
   183   _jvm_user_nanos = jvm_user_nanos;
   184   _jvm_system_nanos = jvm_system_nanos;
   186   return result;
   187 #else
   188   return FUNCTIONALITY_NOT_IMPLEMENTED;
   189 #endif
   190 }
   192 int CPUPerformanceInterface::CPUPerformance::context_switch_rate(double* rate) {
   193 #ifdef __APPLE__
   194   mach_port_t task = mach_task_self();
   195   mach_msg_type_number_t task_info_count = TASK_INFO_MAX;
   196   task_info_data_t task_info_data;
   197   kern_return_t kr = task_info(task, TASK_EVENTS_INFO, (task_info_t)task_info_data, &task_info_count);
   198   if (kr != KERN_SUCCESS) {
   199     return OS_ERR;
   200   }
   202   int result = OS_OK;
   203   if (_total_csr_nanos == 0 || _jvm_context_switches == 0) {
   204     // First call just set initial values.
   205     result = OS_ERR;
   206   }
   208   long jvm_context_switches = ((task_events_info_t)task_info_data)->csw;
   210   long total_csr_nanos;
   211   if(!now_in_nanos(&total_csr_nanos)) {
   212     return OS_ERR;
   213   }
   214   double delta_in_sec = (double)(total_csr_nanos - _total_csr_nanos) / NANOS_PER_SEC;
   215   if (delta_in_sec == 0.0) {
   216     // Avoid division by zero
   217     return OS_ERR;
   218   }
   220   *rate = (jvm_context_switches - _jvm_context_switches) / delta_in_sec;
   222   _jvm_context_switches = jvm_context_switches;
   223   _total_csr_nanos = total_csr_nanos;
   225   return result;
   226 #else
   227   return FUNCTIONALITY_NOT_IMPLEMENTED;
   228 #endif
   229 }
   231 CPUPerformanceInterface::CPUPerformanceInterface() {
   232   _impl = NULL;
   233 }
   235 bool CPUPerformanceInterface::initialize() {
   236   _impl = new CPUPerformanceInterface::CPUPerformance();
   237   return _impl != NULL && _impl->initialize();
   238 }
   240 CPUPerformanceInterface::~CPUPerformanceInterface() {
   241   if (_impl != NULL) {
   242     delete _impl;
   243   }
   244 }
   246 int CPUPerformanceInterface::cpu_load(int which_logical_cpu, double* cpu_load) const {
   247   return _impl->cpu_load(which_logical_cpu, cpu_load);
   248 }
   250 int CPUPerformanceInterface::cpu_load_total_process(double* cpu_load) const {
   251   return _impl->cpu_load_total_process(cpu_load);
   252 }
   254 int CPUPerformanceInterface::cpu_loads_process(double* pjvmUserLoad, double* pjvmKernelLoad, double* psystemTotalLoad) const {
   255   return _impl->cpu_loads_process(pjvmUserLoad, pjvmKernelLoad, psystemTotalLoad);
   256 }
   258 int CPUPerformanceInterface::context_switch_rate(double* rate) const {
   259   return _impl->context_switch_rate(rate);
   260 }
   262 class SystemProcessInterface::SystemProcesses : public CHeapObj<mtInternal> {
   263   friend class SystemProcessInterface;
   264  private:
   265   SystemProcesses();
   266   bool initialize();
   267   SystemProcesses(const SystemProcesses& rhs); // no impl
   268   SystemProcesses& operator=(const SystemProcesses& rhs); // no impl
   269   ~SystemProcesses();
   271   //information about system processes
   272   int system_processes(SystemProcess** system_processes, int* no_of_sys_processes) const;
   273 };
   275 SystemProcessInterface::SystemProcesses::SystemProcesses() {
   276 }
   278 bool SystemProcessInterface::SystemProcesses::initialize() {
   279   return true;
   280 }
   282 SystemProcessInterface::SystemProcesses::~SystemProcesses() {
   283 }
   284 int SystemProcessInterface::SystemProcesses::system_processes(SystemProcess** system_processes, int* no_of_sys_processes) const {
   285   assert(system_processes != NULL, "system_processes pointer is NULL!");
   286   assert(no_of_sys_processes != NULL, "system_processes counter pointer is NULL!");
   287 #ifdef __APPLE__
   288   pid_t* pids = NULL;
   289   int pid_count = 0;
   290   ResourceMark rm;
   292   int try_count = 0;
   293   while (pids == NULL) {
   294     // Find out buffer size
   295     size_t pids_bytes = proc_listpids(PROC_ALL_PIDS, 0, NULL, 0);
   296     if (pids_bytes <= 0) {
   297       return OS_ERR;
   298     }
   299     pid_count = pids_bytes / sizeof(pid_t);
   300     pids = NEW_RESOURCE_ARRAY(pid_t, pid_count);
   301     memset(pids, 0, pids_bytes);
   303     pids_bytes = proc_listpids(PROC_ALL_PIDS, 0, pids, pids_bytes);
   304     if (pids_bytes <= 0) {
   305        // couldn't fit buffer, retry.
   306       FREE_RESOURCE_ARRAY(pid_t, pids, pid_count);
   307       pids = NULL;
   308       try_count++;
   309       if (try_count > 3) {
   310       return OS_ERR;
   311       }
   312     } else {
   313       pid_count = pids_bytes / sizeof(pid_t);
   314     }
   315   }
   317   int process_count = 0;
   318   SystemProcess* next = NULL;
   319   for (int i = 0; i < pid_count; i++) {
   320     pid_t pid = pids[i];
   321     if (pid != 0) {
   322       char buffer[PROC_PIDPATHINFO_MAXSIZE];
   323       memset(buffer, 0 , sizeof(buffer));
   324       if (proc_pidpath(pid, buffer, sizeof(buffer)) != -1) {
   325         int length = strlen(buffer);
   326         if (length > 0) {
   327           SystemProcess* current = new SystemProcess();
   328           char * path = NEW_C_HEAP_ARRAY(char, length + 1, mtInternal);
   329           strcpy(path, buffer);
   330           current->set_path(path);
   331           current->set_pid((int)pid);
   332           current->set_next(next);
   333           next = current;
   334           process_count++;
   335         }
   336       }
   337     }
   338   }
   340   *no_of_sys_processes = process_count;
   341   *system_processes = next;
   343   return OS_OK;
   344 #endif
   345   return FUNCTIONALITY_NOT_IMPLEMENTED;
   346 }
   348 int SystemProcessInterface::system_processes(SystemProcess** system_procs, int* no_of_sys_processes) const {
   349   return _impl->system_processes(system_procs, no_of_sys_processes);
   350 }
   352 SystemProcessInterface::SystemProcessInterface() {
   353   _impl = NULL;
   354 }
   356 bool SystemProcessInterface::initialize() {
   357   _impl = new SystemProcessInterface::SystemProcesses();
   358   return _impl != NULL && _impl->initialize();
   359 }
   361 SystemProcessInterface::~SystemProcessInterface() {
   362   if (_impl != NULL) {
   363     delete _impl;
   364  }
   365 }
   367 CPUInformationInterface::CPUInformationInterface() {
   368   _cpu_info = NULL;
   369 }
   371 bool CPUInformationInterface::initialize() {
   372   _cpu_info = new CPUInformation();
   374   if (NULL == _cpu_info) {
   375     return false;
   376   }
   377   _cpu_info->set_number_of_hardware_threads(VM_Version_Ext::number_of_threads());
   378   _cpu_info->set_number_of_cores(VM_Version_Ext::number_of_cores());
   379   _cpu_info->set_number_of_sockets(VM_Version_Ext::number_of_sockets());
   380   _cpu_info->set_cpu_name(VM_Version_Ext::cpu_name());
   381   _cpu_info->set_cpu_description(VM_Version_Ext::cpu_description());
   383   return true;
   384 }
   386 CPUInformationInterface::~CPUInformationInterface() {
   387   if (_cpu_info != NULL) {
   388     if (_cpu_info->cpu_name() != NULL) {
   389       const char* cpu_name = _cpu_info->cpu_name();
   390       FREE_C_HEAP_ARRAY(char, cpu_name, mtInternal);
   391       _cpu_info->set_cpu_name(NULL);
   392     }
   393     if (_cpu_info->cpu_description() != NULL) {
   394       const char* cpu_desc = _cpu_info->cpu_description();
   395       FREE_C_HEAP_ARRAY(char, cpu_desc, mtInternal);
   396       _cpu_info->set_cpu_description(NULL);
   397     }
   398     delete _cpu_info;
   399   }
   400 }
   402 int CPUInformationInterface::cpu_information(CPUInformation& cpu_info) {
   403   if (NULL == _cpu_info) {
   404     return OS_ERR;
   405   }
   407   cpu_info = *_cpu_info; // shallow copy assignment
   408   return OS_OK;
   409 }
   411 class NetworkPerformanceInterface::NetworkPerformance : public CHeapObj<mtInternal> {
   412   friend class NetworkPerformanceInterface;
   413  private:
   414   NetworkPerformance();
   415   NetworkPerformance(const NetworkPerformance& rhs); // no impl
   416   NetworkPerformance& operator=(const NetworkPerformance& rhs); // no impl
   417   bool initialize();
   418   ~NetworkPerformance();
   419   int network_utilization(NetworkInterface** network_interfaces) const;
   420 };
   422 NetworkPerformanceInterface::NetworkPerformance::NetworkPerformance() {
   423 }
   425 bool NetworkPerformanceInterface::NetworkPerformance::initialize() {
   426   return true;
   427 }
   429 NetworkPerformanceInterface::NetworkPerformance::~NetworkPerformance() {
   430 }
   432 int NetworkPerformanceInterface::NetworkPerformance::network_utilization(NetworkInterface** network_interfaces) const {
   433   size_t len;
   434   int mib[] = {CTL_NET, PF_ROUTE, /* protocol number */ 0, /* address family */ 0, NET_RT_IFLIST2, /* NET_RT_FLAGS mask*/ 0};
   435   if (sysctl(mib, sizeof(mib) / sizeof(mib[0]), NULL, &len, NULL, 0) != 0) {
   436     return OS_ERR;
   437   }
   438   uint8_t* buf = NEW_RESOURCE_ARRAY(uint8_t, len);
   439   if (sysctl(mib, sizeof(mib) / sizeof(mib[0]), buf, &len, NULL, 0) != 0) {
   440     return OS_ERR;
   441   }
   443   size_t index = 0;
   444   NetworkInterface* ret = NULL;
   445   while (index < len) {
   446     if_msghdr* msghdr = reinterpret_cast<if_msghdr*>(buf + index);
   447     index += msghdr->ifm_msglen;
   449     if (msghdr->ifm_type != RTM_IFINFO2) {
   450       continue;
   451     }
   453     if_msghdr2* msghdr2 = reinterpret_cast<if_msghdr2*>(msghdr);
   454     sockaddr_dl* sockaddr = reinterpret_cast<sockaddr_dl*>(msghdr2 + 1);
   456     // The interface name is not necessarily NUL-terminated
   457     char name_buf[128];
   458     size_t name_len = MIN2(sizeof(name_buf) - 1, static_cast<size_t>(sockaddr->sdl_nlen));
   459     strncpy(name_buf, sockaddr->sdl_data, name_len);
   460     name_buf[name_len] = '\0';
   462     uint64_t bytes_in = msghdr2->ifm_data.ifi_ibytes;
   463     uint64_t bytes_out = msghdr2->ifm_data.ifi_obytes;
   465     NetworkInterface* cur = new NetworkInterface(name_buf, bytes_in, bytes_out, ret);
   466     ret = cur;
   467   }
   469   *network_interfaces = ret;
   471   return OS_OK;
   472 }
   474 NetworkPerformanceInterface::NetworkPerformanceInterface() {
   475   _impl = NULL;
   476 }
   478 NetworkPerformanceInterface::~NetworkPerformanceInterface() {
   479   if (_impl != NULL) {
   480     delete _impl;
   481   }
   482 }
   484 bool NetworkPerformanceInterface::initialize() {
   485   _impl = new NetworkPerformanceInterface::NetworkPerformance();
   486   return _impl != NULL && _impl->initialize();
   487 }
   489 int NetworkPerformanceInterface::network_utilization(NetworkInterface** network_interfaces) const {
   490   return _impl->network_utilization(network_interfaces);
   491 }

mercurial