Book a Demo!
CoCalc Logo Icon
StoreFeaturesDocsShareSupportNewsAboutPoliciesSign UpSign In
PojavLauncherTeam
GitHub Repository: PojavLauncherTeam/openj9
Path: blob/master/runtime/compiler/env/CpuUtilization.hpp
6000 views
1
/*******************************************************************************
2
* Copyright (c) 2000, 2020 IBM Corp. and others
3
*
4
* This program and the accompanying materials are made available under
5
* the terms of the Eclipse Public License 2.0 which accompanies this
6
* distribution and is available at https://www.eclipse.org/legal/epl-2.0/
7
* or the Apache License, Version 2.0 which accompanies this distribution and
8
* is available at https://www.apache.org/licenses/LICENSE-2.0.
9
*
10
* This Source Code may also be made available under the following
11
* Secondary Licenses when the conditions for such availability set
12
* forth in the Eclipse Public License, v. 2.0 are satisfied: GNU
13
* General Public License, version 2 with the GNU Classpath
14
* Exception [1] and GNU General Public License, version 2 with the
15
* OpenJDK Assembly Exception [2].
16
*
17
* [1] https://www.gnu.org/software/classpath/license.html
18
* [2] http://openjdk.java.net/legal/assembly-exception.html
19
*
20
* SPDX-License-Identifier: EPL-2.0 OR Apache-2.0 OR GPL-2.0 WITH Classpath-exception-2.0 OR LicenseRef-GPL-2.0 WITH Assembly-exception
21
*******************************************************************************/
22
23
#ifndef CPUUTILIZATION_HPP
24
#define CPUUTILIZATION_HPP
25
26
#include <stdint.h>
27
#include "jni.h"
28
#include "j9.h"
29
#include "j9port.h"
30
#include "env/TRMemory.hpp"
31
#include "il/DataTypes.hpp"
32
33
namespace TR { class PersistentInfo; }
34
35
// TODO: maybe move this to a global config?
36
#define INITIAL_USAGE (77) // assume relatively high usage at start
37
#define INITIAL_IDLE (100 - INITIAL_USAGE)
38
#define CPU_UTIL_ARRAY_DEFAULT_SIZE 12
39
40
//------------------------- class CpuUtilization ----------------------------
41
// Class that maintains info about CPU utilization for a given period of time
42
//---------------------------------------------------------------------------
43
44
//---------------------------------------------------------------------------
45
// WARNING
46
//
47
// The values obtained by this class have been observed during testing to be
48
// inaccurate within 4% in either direction. That is, a usage value of 10%
49
// could actually be anywhere from 6% to 14%.
50
//
51
// This is both because integer arithmetic is used in calculations, and
52
// because the information returned by the portlib is slightly inconsistent
53
// since it is obtained from two separate calls (and the time reference comes
54
// from only one of the calls).
55
//---------------------------------------------------------------------------
56
class CpuUtilization
57
{
58
59
public:
60
61
TR_PERSISTENT_ALLOC(TR_Memory::PersistentInfo);
62
63
CpuUtilization(J9JITConfig *jitConfig);
64
65
typedef struct CpuUsageCircularBuffer
66
{
67
int64_t _timeStamp;
68
int64_t _sampleSystemCpu;
69
int64_t _sampleJvmCpu;
70
} CpuUsageCircularBuffer;
71
72
bool isFunctional() const { return _isFunctional; }
73
int32_t getCpuUsage() const { return _cpuUsage; }
74
int32_t getCpuIdle() const { return _cpuIdle; }
75
int32_t getVmCpuUsage() const { return _vmCpuUsage; }
76
int32_t getAvgCpuUsage() const { return _avgCpuUsage; }
77
int32_t getAvgCpuIdle() const { return _avgCpuIdle; }
78
int64_t getUptime() const { return _prevMachineUptime; } // in nanoseconds
79
int64_t getLastMeasurementInterval() const { return _prevIntervalLength; } // in nanoseconds
80
int64_t getVmTotalCpuTime() const { return _prevVmSysTime + _prevVmUserTime; }
81
int32_t getCpuUtil(J9JITConfig *jitConfig, J9SysinfoCPUTime *machineCpuStats, j9thread_process_time_t *vmCpuStats);
82
int32_t updateCpuUtil(J9JITConfig *jitConfig);
83
void disable() { _isFunctional = false;
84
_cpuUsage = _cpuIdle = _vmCpuUsage = _avgCpuUsage = _avgCpuIdle = -1;
85
disableCpuUsageCircularBuffer(); }
86
87
// Circular Buffer related functions
88
CpuUsageCircularBuffer *getCpuUsageCircularBuffer() const { return _cpuUsageCircularBuffer; }
89
void disableCpuUsageCircularBuffer() { _isCpuUsageCircularBufferFunctional = false; }
90
int32_t getCircularBufferIndex() const { return _cpuUsageCircularBufferIndex; }
91
int32_t getCircularBufferSize() const { return _cpuUsageCircularBufferSize; }
92
bool isCpuUsageCircularBufferFunctional() const { return (_isFunctional && _isCpuUsageCircularBufferFunctional); }
93
int32_t updateCpuUsageCircularBuffer(J9JITConfig *jitConfig);
94
95
private:
96
97
int32_t _cpuUsage; // percentage of used CPU on the whole machine for the last update interval
98
int32_t _cpuIdle; // percentage of idle CPU on the whole machine for the last update interval
99
int32_t _vmCpuUsage; // percentage of used CPU by the VM for the last update interval
100
int32_t _avgCpuUsage; // percentage of time each processor is used on average (0..100)
101
int32_t _avgCpuIdle; // percentage of time each processor is idle on average (0..100)
102
103
int64_t _prevIntervalLength; // the duration (in ns) of the last update interval
104
105
// values recorded at start of this update interval
106
int64_t _prevMachineUptime; // absolute value (in ns) of machine uptime
107
int64_t _prevMachineCpuTime; // absolute value (in ns) of used CPU time on the machine
108
int64_t _prevVmSysTime; // absolute value (in ns) of time VM spent in kernel space
109
int64_t _prevVmUserTime; // absolute value (in ns) of time VM spent in user space
110
111
CpuUsageCircularBuffer *_cpuUsageCircularBuffer; // Circular buffer containing timestamp, system cpu usage sample, and jvm cpu use sample
112
int32_t _cpuUsageCircularBufferIndex; // Current index of the buffer; contains the oldest data. Subtract 1 to get the most recent data
113
int32_t _cpuUsageCircularBufferSize; // Size of the circular buffer
114
115
bool _isFunctional;
116
bool _isCpuUsageCircularBufferFunctional;
117
118
}; // class CpuUtilization
119
120
// How to use it:
121
// IMPORTANT: The update() and getCpuTimeNow() routines MUST be called
122
// only by the thread for which we want to compute CPU utilization
123
// You may call the update() function as often as you want, but the update actually happens only so often.
124
// The update() function will return false if no update took place (too soon to be recomputed)
125
// Use getCpuTime() to find CPU spent in thread from the beginning of the JVM till the last update
126
// Use getCpuTimeNow() to find CPU spent in thread till this moment;
127
// - heavyweight because it invokes OS
128
// - must be called only by the thread for which we want CPu time
129
// Use getThreadLastCpuUtil() to print CPU utilization of the thread during the last interval (should be <= 100)
130
131
namespace TR { class CompilationInfo; }
132
namespace TR {
133
class PersistentInfo;
134
}
135
extern "C" {
136
struct J9JITConfig;
137
}
138
class CpuSelfThreadUtilization
139
{
140
public:
141
TR_PERSISTENT_ALLOC(TR_Memory::PersistentInfo);
142
CpuSelfThreadUtilization(TR::PersistentInfo * persistentInfo, J9JITConfig * jitConfig, int64_t minPeriodNs, int32_t id);
143
bool update();
144
int64_t getCpuTime() const { return _cpuTimeAtLastUpdate; }
145
int64_t getCpuTimeNow() const {PORT_ACCESS_FROM_JITCONFIG(_jitConfig); return j9thread_get_self_cpu_time(j9thread_self()); } // expensive
146
int64_t getTimeOfLastUpdate() const { return _clockTimeAtLastUpdate; } // ns
147
int64_t getLowResolutionClockAtLastUpdate() const { return _lowResolutionClockAtLastUpdate; } // ms
148
int64_t getLastMeasurementInterval() const { return _lastIntervalLength; } // ns
149
int64_t getSecondLastMeasurementInterval() const { return _secondLastIntervalLength; } // ns
150
int64_t getCpuTimeDuringLastInterval() const { return _cpuTimeDuringLastInterval; }
151
int64_t getCpuTimeDuringSecondLastInterval() const { return _cpuTimeDuringSecondLastInterval; }
152
// getThreadLastCpuUtil() returns CPU utilization of thread as a percentage. Values greater than 100 are errors.
153
int32_t getThreadLastCpuUtil() const { return _lastCpuUtil; }
154
int32_t getThreadPrevCpuUtil() const { return _secondLastCpuUtil; }
155
int32_t computeThreadCpuUtilOverLastNns(int64_t validInterval) const; // this one looks at the last two intervals, but not too distant in the past
156
int64_t getCrtTimeNs() const { PORT_ACCESS_FROM_JITCONFIG(_jitConfig); return j9time_current_time_millis() * 1000000; /* j9time_nano_time() */}
157
int32_t getId() const { return _id; }
158
bool isFunctional() const { return _isFunctional; }
159
void setAsUnfunctional();
160
void printInfoToVlog() const;
161
162
private:
163
J9JITConfig *_jitConfig;
164
TR::PersistentInfo *_persistentInfo;
165
166
int64_t _minMeasurementIntervalLength; // update only if at least that much time has passed since the last update
167
int64_t _clockTimeAtLastUpdate; // time when stats for last interval were computed (ns)
168
uint64_t _lowResolutionClockAtLastUpdate; // this is based on the fast but inaccurate time maintained in persistentinfo (ms)
169
int64_t _cpuTimeAtLastUpdate; // cpu time spent in thread at the time of last update (since the start of the process)
170
int64_t _cpuTimeDuringLastInterval; // cpu time spent in thread during the last measurement interval
171
int64_t _lastIntervalLength; // duration of the last measurement interval
172
int32_t _lastCpuUtil; // CPU utilization of the thread during the last interval
173
174
int64_t _cpuTimeDuringSecondLastInterval; // cpu time spent in thread during the second last measurement interval (precedes last interval)
175
int64_t _secondLastIntervalLength; // duration of the second last measurement interval
176
int32_t _secondLastCpuUtil; // CPU utilization of the thread during the second last interval
177
178
int32_t _id; // some identifier; e.g. compilation thread id
179
bool _isFunctional;
180
}; // CpuSelfThreadUtilization
181
182
183
// Note, an object of this type is embedded into TR::CompilationInfo which is
184
// zeroed out at construction time. Thus, TR_CpuEntitlement cannot have virtual
185
// functions. If virtual functions are added to TR_CpuEntitlement then we need
186
// to allocate it dynamically and store a pointer into TR::CompilationInfo
187
struct TR_CpuEntitlement
188
{
189
public:
190
// The constructor cannot set all fields correctly because we have to make
191
// sure te portlib is up and running
192
void init(J9JITConfig *jitConfig)
193
{
194
/* Couple of issues were discovered when the support for hypervisor was enabled.
195
* When JVM ran on VMWare, then the port library loaded libvmGuestLib.so which
196
* interferes with implementation of some of j.l.Math methods.
197
* The library also causes JVM to core dump when an application is using libjsig.so
198
* for signal chaining.
199
* For these reasons, support for hypervisor is being disabled until the issues with
200
* VMWare library are resolved.
201
*/
202
_hypervisorPresent = TR_no;
203
_jitConfig = jitConfig;
204
computeAndCacheCpuEntitlement();
205
}
206
bool isHypervisorPresent();
207
void computeAndCacheCpuEntitlement(); // used during bootstrap and periodically in samplerThreadProc
208
uint32_t getNumTargetCPUs() const { return _numTargetCpu; } // num CPUs the JVM is pinned to. Guaranteed >= 1
209
double getGuestCpuEntitlement() const { return _guestCpuEntitlement; } // as given by the hypervisor; 0 if error or no hypervisor
210
double getJvmCpuEntitlement() const { return _jvmCpuEntitlement; } // smallest of _numTargetCpu and _guestCpuEntitlement
211
212
private:
213
double computeGuestCpuEntitlement() const; // this does not check for isHypervisorPresent, so don't call it directly
214
215
TR_YesNoMaybe _hypervisorPresent;
216
uint32_t _numTargetCpu;
217
double _guestCpuEntitlement;
218
double _jvmCpuEntitlement;
219
J9JITConfig * _jitConfig;
220
};
221
222
#endif // CPUUTILIZATION_HPP
223
224