jdk

Форк
0
/
os_perf_bsd.cpp 
485 строк · 14.0 Кб
1
/*
2
 * Copyright (c) 2012, 2024, 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 "runtime/vm_version.hpp"
30
#include "utilities/globalDefinitions.hpp"
31

32
#ifdef __APPLE__
33
  #import <libproc.h>
34
  #include <sys/time.h>
35
  #include <sys/sysctl.h>
36
  #include <mach/mach.h>
37
  #include <mach/task_info.h>
38
  #include <sys/socket.h>
39
  #include <net/if.h>
40
  #include <net/if_dl.h>
41
  #include <net/route.h>
42
  #include <sys/times.h>
43
#endif
44

45
static const double NANOS_PER_SEC = 1000000000.0;
46

47
class CPUPerformanceInterface::CPUPerformance : public CHeapObj<mtInternal> {
48
   friend class CPUPerformanceInterface;
49
 private:
50
#ifdef __APPLE__
51
  uint64_t _jvm_real;
52
  uint64_t _total_csr_nanos;
53
  uint64_t _jvm_user;
54
  uint64_t _jvm_system;
55
  long _jvm_context_switches;
56
  long _used_ticks;
57
  long _total_ticks;
58
  int  _active_processor_count;
59

60
  bool now_in_nanos(uint64_t* resultp) {
61
    struct timespec tp;
62
    int status = clock_gettime(CLOCK_REALTIME, &tp);
63
    assert(status == 0, "clock_gettime error: %s", os::strerror(errno));
64
    if (status != 0) {
65
      return false;
66
    }
67
    *resultp = tp.tv_sec * NANOS_PER_SEC + tp.tv_nsec;
68
    return true;
69
  }
70
#endif
71

72
  double normalize(double value) {
73
    return MIN2<double>(MAX2<double>(value, 0.0), 1.0);
74
  }
75
  int cpu_load(int which_logical_cpu, double* cpu_load);
76
  int context_switch_rate(double* rate);
77
  int cpu_load_total_process(double* cpu_load);
78
  int cpu_loads_process(double* pjvmUserLoad, double* pjvmKernelLoad, double* psystemTotalLoad);
79

80
  NONCOPYABLE(CPUPerformance);
81

82
 public:
83
  CPUPerformance();
84
  bool initialize();
85
  ~CPUPerformance();
86
};
87

88
CPUPerformanceInterface::CPUPerformance::CPUPerformance() {
89
#ifdef __APPLE__
90
  _jvm_real = 0;
91
  _total_csr_nanos= 0;
92
  _jvm_context_switches = 0;
93
  _jvm_user = 0;
94
  _jvm_system = 0;
95
  _used_ticks = 0;
96
  _total_ticks = 0;
97
  _active_processor_count = 0;
98
#endif
99
}
100

101
bool CPUPerformanceInterface::CPUPerformance::initialize() {
102
  return true;
103
}
104

105
CPUPerformanceInterface::CPUPerformance::~CPUPerformance() {
106
}
107

108
int CPUPerformanceInterface::CPUPerformance::cpu_load(int which_logical_cpu, double* cpu_load) {
109
  return FUNCTIONALITY_NOT_IMPLEMENTED;
110
}
111

112
int CPUPerformanceInterface::CPUPerformance::cpu_load_total_process(double* cpu_load) {
113
#ifdef __APPLE__
114
  host_name_port_t host = mach_host_self();
115
  host_flavor_t flavor = HOST_CPU_LOAD_INFO;
116
  mach_msg_type_number_t host_info_count = HOST_CPU_LOAD_INFO_COUNT;
117
  host_cpu_load_info_data_t cpu_load_info;
118

119
  kern_return_t kr = host_statistics(host, flavor, (host_info_t)&cpu_load_info, &host_info_count);
120
  if (kr != KERN_SUCCESS) {
121
    return OS_ERR;
122
  }
123

124
  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];
125
  long total_ticks = used_ticks + cpu_load_info.cpu_ticks[CPU_STATE_IDLE];
126

127
  if (_used_ticks == 0 || _total_ticks == 0) {
128
    // First call, just set the values
129
    _used_ticks  = used_ticks;
130
    _total_ticks = total_ticks;
131
    return OS_ERR;
132
  }
133

134
  long used_delta  = used_ticks - _used_ticks;
135
  long total_delta = total_ticks - _total_ticks;
136

137
  _used_ticks  = used_ticks;
138
  _total_ticks = total_ticks;
139

140
  if (total_delta == 0) {
141
    // Avoid division by zero
142
    return OS_ERR;
143
  }
144

145
  *cpu_load = (double)used_delta / total_delta;
146

147
  return OS_OK;
148
#else
149
  return FUNCTIONALITY_NOT_IMPLEMENTED;
150
#endif
151
}
152

153
int CPUPerformanceInterface::CPUPerformance::cpu_loads_process(double* pjvmUserLoad, double* pjvmKernelLoad, double* psystemTotalLoad) {
154
#ifdef __APPLE__
155
  int result = cpu_load_total_process(psystemTotalLoad);
156

157
  struct tms buf;
158
  clock_t jvm_real = times(&buf);
159
  if (jvm_real == (clock_t) (-1)) {
160
    return OS_ERR;
161
  }
162

163
  int active_processor_count = os::active_processor_count();
164
  uint64_t jvm_user = buf.tms_utime;
165
  uint64_t jvm_system = buf.tms_stime;
166

167
  if (active_processor_count != _active_processor_count) {
168
    // Change in active processor count
169
    result = OS_ERR;
170
  } else {
171
    uint64_t delta = active_processor_count * (jvm_real - _jvm_real);
172
    if (delta == 0) {
173
      // Avoid division by zero
174
      return OS_ERR;
175
    }
176

177
    *pjvmUserLoad = normalize((double)(jvm_user - _jvm_user) / delta);
178
    *pjvmKernelLoad = normalize((double)(jvm_system - _jvm_system) / delta);
179
  }
180

181
  _active_processor_count = active_processor_count;
182
  _jvm_real = jvm_real;
183
  _jvm_user = jvm_user;
184
  _jvm_system = jvm_system;
185

186
  return result;
187
#else
188
  return FUNCTIONALITY_NOT_IMPLEMENTED;
189
#endif
190
}
191

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
  }
201

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
  }
207

208
  long jvm_context_switches = ((task_events_info_t)task_info_data)->csw;
209

210
  uint64_t 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
  }
219

220
  *rate = (jvm_context_switches - _jvm_context_switches) / delta_in_sec;
221

222
  _jvm_context_switches = jvm_context_switches;
223
  _total_csr_nanos = total_csr_nanos;
224

225
  return result;
226
#else
227
  return FUNCTIONALITY_NOT_IMPLEMENTED;
228
#endif
229
}
230

231
CPUPerformanceInterface::CPUPerformanceInterface() {
232
  _impl = nullptr;
233
}
234

235
bool CPUPerformanceInterface::initialize() {
236
  _impl = new CPUPerformanceInterface::CPUPerformance();
237
  return _impl->initialize();
238
}
239

240
CPUPerformanceInterface::~CPUPerformanceInterface() {
241
  if (_impl != nullptr) {
242
    delete _impl;
243
  }
244
}
245

246
int CPUPerformanceInterface::cpu_load(int which_logical_cpu, double* cpu_load) const {
247
  return _impl->cpu_load(which_logical_cpu, cpu_load);
248
}
249

250
int CPUPerformanceInterface::cpu_load_total_process(double* cpu_load) const {
251
  return _impl->cpu_load_total_process(cpu_load);
252
}
253

254
int CPUPerformanceInterface::cpu_loads_process(double* pjvmUserLoad, double* pjvmKernelLoad, double* psystemTotalLoad) const {
255
  return _impl->cpu_loads_process(pjvmUserLoad, pjvmKernelLoad, psystemTotalLoad);
256
}
257

258
int CPUPerformanceInterface::context_switch_rate(double* rate) const {
259
  return _impl->context_switch_rate(rate);
260
}
261

262
class SystemProcessInterface::SystemProcesses : public CHeapObj<mtInternal> {
263
  friend class SystemProcessInterface;
264
 private:
265
  SystemProcesses();
266
  bool initialize();
267
  NONCOPYABLE(SystemProcesses);
268
  ~SystemProcesses();
269

270
  //information about system processes
271
  int system_processes(SystemProcess** system_processes, int* no_of_sys_processes) const;
272
};
273

274
SystemProcessInterface::SystemProcesses::SystemProcesses() {
275
}
276

277
bool SystemProcessInterface::SystemProcesses::initialize() {
278
  return true;
279
}
280

281
SystemProcessInterface::SystemProcesses::~SystemProcesses() {
282
}
283
int SystemProcessInterface::SystemProcesses::system_processes(SystemProcess** system_processes, int* no_of_sys_processes) const {
284
  assert(system_processes != nullptr, "system_processes pointer is null!");
285
  assert(no_of_sys_processes != nullptr, "system_processes counter pointer is null!");
286
#ifdef __APPLE__
287
  pid_t* pids = nullptr;
288
  int pid_count = 0;
289
  ResourceMark rm;
290

291
  int try_count = 0;
292
  while (pids == nullptr) {
293
    // Find out buffer size
294
    size_t pids_bytes = proc_listpids(PROC_ALL_PIDS, 0, nullptr, 0);
295
    if (pids_bytes <= 0) {
296
      return OS_ERR;
297
    }
298
    pid_count = pids_bytes / sizeof(pid_t);
299
    pids = NEW_RESOURCE_ARRAY(pid_t, pid_count);
300
    memset(pids, 0, pids_bytes);
301

302
    pids_bytes = proc_listpids(PROC_ALL_PIDS, 0, pids, pids_bytes);
303
    if (pids_bytes <= 0) {
304
       // couldn't fit buffer, retry.
305
      FREE_RESOURCE_ARRAY(pid_t, pids, pid_count);
306
      pids = nullptr;
307
      try_count++;
308
      if (try_count > 3) {
309
      return OS_ERR;
310
      }
311
    } else {
312
      pid_count = pids_bytes / sizeof(pid_t);
313
    }
314
  }
315

316
  int process_count = 0;
317
  SystemProcess* next = nullptr;
318
  for (int i = 0; i < pid_count; i++) {
319
    pid_t pid = pids[i];
320
    if (pid != 0) {
321
      char buffer[PROC_PIDPATHINFO_MAXSIZE];
322
      memset(buffer, 0 , sizeof(buffer));
323
      if (proc_pidpath(pid, buffer, sizeof(buffer)) != -1) {
324
        int length = strlen(buffer);
325
        if (length > 0) {
326
          SystemProcess* current = new SystemProcess();
327
          char * path = NEW_C_HEAP_ARRAY(char, length + 1, mtInternal);
328
          strcpy(path, buffer);
329
          current->set_path(path);
330
          current->set_pid((int)pid);
331
          current->set_next(next);
332
          next = current;
333
          process_count++;
334
        }
335
      }
336
    }
337
  }
338

339
  *no_of_sys_processes = process_count;
340
  *system_processes = next;
341

342
  return OS_OK;
343
#endif
344
  return FUNCTIONALITY_NOT_IMPLEMENTED;
345
}
346

347
int SystemProcessInterface::system_processes(SystemProcess** system_procs, int* no_of_sys_processes) const {
348
  return _impl->system_processes(system_procs, no_of_sys_processes);
349
}
350

351
SystemProcessInterface::SystemProcessInterface() {
352
  _impl = nullptr;
353
}
354

355
bool SystemProcessInterface::initialize() {
356
  _impl = new SystemProcessInterface::SystemProcesses();
357
  return _impl->initialize();
358
}
359

360
SystemProcessInterface::~SystemProcessInterface() {
361
  if (_impl != nullptr) {
362
    delete _impl;
363
 }
364
}
365

366
CPUInformationInterface::CPUInformationInterface() {
367
  _cpu_info = nullptr;
368
}
369

370
bool CPUInformationInterface::initialize() {
371
  _cpu_info = new CPUInformation();
372
  VM_Version::initialize_cpu_information();
373
  _cpu_info->set_number_of_hardware_threads(VM_Version::number_of_threads());
374
  _cpu_info->set_number_of_cores(VM_Version::number_of_cores());
375
  _cpu_info->set_number_of_sockets(VM_Version::number_of_sockets());
376
  _cpu_info->set_cpu_name(VM_Version::cpu_name());
377
  _cpu_info->set_cpu_description(VM_Version::cpu_description());
378
  return true;
379
}
380

381
CPUInformationInterface::~CPUInformationInterface() {
382
  if (_cpu_info != nullptr) {
383
    if (_cpu_info->cpu_name() != nullptr) {
384
      const char* cpu_name = _cpu_info->cpu_name();
385
      FREE_C_HEAP_ARRAY(char, cpu_name);
386
      _cpu_info->set_cpu_name(nullptr);
387
    }
388
    if (_cpu_info->cpu_description() != nullptr) {
389
      const char* cpu_desc = _cpu_info->cpu_description();
390
      FREE_C_HEAP_ARRAY(char, cpu_desc);
391
      _cpu_info->set_cpu_description(nullptr);
392
    }
393
    delete _cpu_info;
394
  }
395
}
396

397
int CPUInformationInterface::cpu_information(CPUInformation& cpu_info) {
398
  if (nullptr == _cpu_info) {
399
    return OS_ERR;
400
  }
401

402
  cpu_info = *_cpu_info; // shallow copy assignment
403
  return OS_OK;
404
}
405

406
class NetworkPerformanceInterface::NetworkPerformance : public CHeapObj<mtInternal> {
407
  friend class NetworkPerformanceInterface;
408
 private:
409
  NetworkPerformance();
410
  NONCOPYABLE(NetworkPerformance);
411
  bool initialize();
412
  ~NetworkPerformance();
413
  int network_utilization(NetworkInterface** network_interfaces) const;
414
};
415

416
NetworkPerformanceInterface::NetworkPerformance::NetworkPerformance() {
417
}
418

419
bool NetworkPerformanceInterface::NetworkPerformance::initialize() {
420
  return true;
421
}
422

423
NetworkPerformanceInterface::NetworkPerformance::~NetworkPerformance() {
424
}
425

426
int NetworkPerformanceInterface::NetworkPerformance::network_utilization(NetworkInterface** network_interfaces) const {
427
  size_t len;
428
  int mib[] = {CTL_NET, PF_ROUTE, /* protocol number */ 0, /* address family */ 0, NET_RT_IFLIST2, /* NET_RT_FLAGS mask*/ 0};
429
  if (sysctl(mib, sizeof(mib) / sizeof(mib[0]), nullptr, &len, nullptr, 0) != 0) {
430
    return OS_ERR;
431
  }
432
  uint8_t* buf = NEW_RESOURCE_ARRAY(uint8_t, len);
433
  if (sysctl(mib, sizeof(mib) / sizeof(mib[0]), buf, &len, nullptr, 0) != 0) {
434
    return OS_ERR;
435
  }
436

437
  size_t index = 0;
438
  NetworkInterface* ret = nullptr;
439
  while (index < len) {
440
    if_msghdr* msghdr = reinterpret_cast<if_msghdr*>(buf + index);
441
    index += msghdr->ifm_msglen;
442

443
    if (msghdr->ifm_type != RTM_IFINFO2) {
444
      continue;
445
    }
446

447
    if_msghdr2* msghdr2 = reinterpret_cast<if_msghdr2*>(msghdr);
448
    sockaddr_dl* sockaddr = reinterpret_cast<sockaddr_dl*>(msghdr2 + 1);
449

450
    // The interface name is not necessarily NUL-terminated
451
    char name_buf[128];
452
    size_t name_len = MIN2(sizeof(name_buf) - 1, static_cast<size_t>(sockaddr->sdl_nlen));
453
    strncpy(name_buf, sockaddr->sdl_data, name_len);
454
    name_buf[name_len] = '\0';
455

456
    uint64_t bytes_in = msghdr2->ifm_data.ifi_ibytes;
457
    uint64_t bytes_out = msghdr2->ifm_data.ifi_obytes;
458

459
    NetworkInterface* cur = new NetworkInterface(name_buf, bytes_in, bytes_out, ret);
460
    ret = cur;
461
  }
462

463
  *network_interfaces = ret;
464

465
  return OS_OK;
466
}
467

468
NetworkPerformanceInterface::NetworkPerformanceInterface() {
469
  _impl = nullptr;
470
}
471

472
NetworkPerformanceInterface::~NetworkPerformanceInterface() {
473
  if (_impl != nullptr) {
474
    delete _impl;
475
  }
476
}
477

478
bool NetworkPerformanceInterface::initialize() {
479
  _impl = new NetworkPerformanceInterface::NetworkPerformance();
480
  return _impl->initialize();
481
}
482

483
int NetworkPerformanceInterface::network_utilization(NetworkInterface** network_interfaces) const {
484
  return _impl->network_utilization(network_interfaces);
485
}
486

Использование cookies

Мы используем файлы cookie в соответствии с Политикой конфиденциальности и Политикой использования cookies.

Нажимая кнопку «Принимаю», Вы даете АО «СберТех» согласие на обработку Ваших персональных данных в целях совершенствования нашего веб-сайта и Сервиса GitVerse, а также повышения удобства их использования.

Запретить использование cookies Вы можете самостоятельно в настройках Вашего браузера.