33
33
34
34
/*
35
35
* Relevant port library API:
36
- *
36
+ *
37
37
* IDATA j9sysinfo_get_CPU_utilization(struct J9PortLibrary *portLibrary, struct J9SysinfoCPUTime *cpuTime)
38
- *
38
+ *
39
39
* typedef struct J9SysinfoCPUTime {
40
40
*
41
41
* I_64 timestamp; // time in nanoseconds from a fixed but arbitrary point in time
42
42
* I_64 cpuTime; // cumulative CPU utilization (sum of system and user time in nanoseconds) of all CPUs on the system.
43
43
* I_32 numberOfCpus; // number of CPUs as reported by the operating system
44
- *
44
+ *
45
45
* } J9SysinfoCPUTime;
46
46
*
47
47
* I_64 j9thread_get_process_times(j9thread_process_time_t * processTime)
48
- *
48
+ *
49
49
* typedef struct j9thread_process_time_t {
50
50
*
51
51
* // for consistency sake, times are stored as I_64s
56
56
*/
57
57
58
58
int32_t CpuUtilization::getCpuUtil (J9JITConfig *jitConfig, J9SysinfoCPUTime *machineCpuStats, j9thread_process_time_t *vmCpuStats)
59
- {
59
+ {
60
60
IDATA portLibraryStatusSys; // port lib call return value for system cpu usage
61
61
IDATA portLibraryStatusVm; // port lib call return value for vm cpu usage
62
-
62
+
63
63
// get access to portlib
64
64
PORT_ACCESS_FROM_JITCONFIG (jitConfig);
65
-
65
+
66
66
// get CPU stats for the machine
67
67
portLibraryStatusSys = j9sysinfo_get_CPU_utilization (machineCpuStats);
68
68
portLibraryStatusVm = j9thread_get_process_times (vmCpuStats);
69
-
69
+
70
70
// if either call failed, disable self
71
71
if (portLibraryStatusSys < 0 || portLibraryStatusVm < 0 )
72
72
{
73
73
disable ();
74
74
return (-1 );
75
75
}
76
-
76
+
77
77
return 0 ;
78
78
}
79
79
80
80
/*
81
81
* Update the values stored inside the object. Only updates the values
82
- * when called more than _minIntervalLength milliseconds after the last
83
- * update.
82
+ * when called more than _minIntervalLength ns after the last update.
84
83
*/
85
84
int CpuUtilization::updateCpuUtil (J9JITConfig *jitConfig)
86
85
{
@@ -89,41 +88,45 @@ int CpuUtilization::updateCpuUtil(J9JITConfig *jitConfig)
89
88
{
90
89
return (-1 );
91
90
}
92
-
91
+
93
92
// portlib data
94
93
J9SysinfoCPUTime machineCpuStats; // stats for overall CPU usage on machine
95
94
j9thread_process_time_t vmCpuStats; // stats for VM's CPU usage
96
-
95
+
97
96
if (getCpuUtil (jitConfig, &machineCpuStats, &vmCpuStats) == -1 )
98
97
return (-1 );
99
-
98
+
100
99
// calculate interval
101
- _prevIntervalLength = machineCpuStats.timestamp - _prevMachineUptime;
102
-
100
+ int64_t elapsedTime = machineCpuStats.timestamp - _prevMachineUptime;
101
+ if (elapsedTime < _minIntervalLength)
102
+ return -1 ; // update not done
103
+
104
+ _prevIntervalLength = elapsedTime;
105
+
103
106
// calculate usage and idle percentages
104
- if (_prevIntervalLength > 0 )
107
+ if (elapsedTime > 0 )
105
108
{
106
109
int64_t prevTotalTimeUsedByVm = _prevVmSysTime + _prevVmUserTime;
107
110
int64_t newTotalTimeUsedByVm = vmCpuStats._systemTime + vmCpuStats._userTime ;
108
-
109
- _cpuUsage = (100 * (machineCpuStats.cpuTime - _prevMachineCpuTime)) / _prevIntervalLength ;
111
+
112
+ _cpuUsage = (100 * (machineCpuStats.cpuTime - _prevMachineCpuTime)) / elapsedTime ;
110
113
_cpuIdle = 100 * machineCpuStats.numberOfCpus - _cpuUsage;
111
- _vmCpuUsage = (100 * (newTotalTimeUsedByVm - prevTotalTimeUsedByVm)) / _prevIntervalLength ;
114
+ _vmCpuUsage = (100 * (newTotalTimeUsedByVm - prevTotalTimeUsedByVm)) / elapsedTime ;
112
115
}
113
-
116
+
114
117
if (machineCpuStats.numberOfCpus > 0 )
115
118
{
116
119
_avgCpuUsage = _cpuUsage / machineCpuStats.numberOfCpus ;
117
120
}
118
-
121
+
119
122
_avgCpuIdle = 100 - _avgCpuUsage;
120
-
123
+
121
124
// remember values for next time
122
125
_prevMachineUptime = machineCpuStats.timestamp ;
123
126
_prevMachineCpuTime = machineCpuStats.cpuTime ;
124
127
_prevVmSysTime = vmCpuStats._systemTime ;
125
128
_prevVmUserTime = vmCpuStats._userTime ;
126
-
129
+
127
130
return 0 ;
128
131
} // updateCpuUtil
129
132
@@ -134,22 +137,22 @@ int32_t CpuUtilization::updateCpuUsageCircularBuffer(J9JITConfig *jitConfig)
134
137
{
135
138
return (-1 );
136
139
}
137
-
140
+
138
141
// portlib data
139
142
J9SysinfoCPUTime machineCpuStats; // stats for overall CPU usage on machine
140
143
j9thread_process_time_t vmCpuStats; // stats for VM's CPU usage
141
-
144
+
142
145
if (getCpuUtil (jitConfig, &machineCpuStats, &vmCpuStats) == -1 )
143
146
return (-1 );
144
-
147
+
145
148
_cpuUsageCircularBuffer[_cpuUsageCircularBufferIndex]._timeStamp = machineCpuStats.timestamp ;
146
149
_cpuUsageCircularBuffer[_cpuUsageCircularBufferIndex]._sampleSystemCpu = machineCpuStats.cpuTime ;
147
150
_cpuUsageCircularBuffer[_cpuUsageCircularBufferIndex]._sampleJvmCpu = vmCpuStats._systemTime + vmCpuStats._userTime ;
148
-
151
+
149
152
_cpuUsageCircularBufferIndex = (_cpuUsageCircularBufferIndex + 1 )%_cpuUsageCircularBufferSize;
150
-
153
+
151
154
return 0 ;
152
-
155
+
153
156
} // updateCpuUsageArray
154
157
155
158
CpuUtilization::CpuUtilization (J9JITConfig *jitConfig):
@@ -160,18 +163,20 @@ CpuUtilization::CpuUtilization(J9JITConfig *jitConfig):
160
163
_avgCpuUsage (INITIAL_USAGE),
161
164
_cpuIdle (INITIAL_IDLE),
162
165
_avgCpuIdle (INITIAL_IDLE),
163
-
166
+
167
+ _minIntervalLength (100000000 ), // 100 ms
168
+
164
169
_prevIntervalLength (0 ),
165
-
170
+
166
171
_prevMachineUptime (0 ),
167
172
_prevMachineCpuTime (0 ),
168
173
_prevVmSysTime (0 ),
169
174
_prevVmUserTime (0 ),
170
-
175
+
171
176
_isFunctional (true ),
172
-
177
+
173
178
_cpuUsageCircularBufferIndex(0 )
174
-
179
+
175
180
{
176
181
// If the circular buffer size is set to 0, disable the circular buffer
177
182
if (TR::Options::_cpuUsageCircularBufferSize == 0 )
@@ -180,26 +185,26 @@ CpuUtilization::CpuUtilization(J9JITConfig *jitConfig):
180
185
_cpuUsageCircularBuffer = NULL ;
181
186
return ;
182
187
}
183
-
188
+
184
189
_isCpuUsageCircularBufferFunctional = true ;
185
-
190
+
186
191
// Enforce a minimum size
187
192
if (TR::Options::_cpuUsageCircularBufferSize < CPU_UTIL_ARRAY_DEFAULT_SIZE)
188
193
_cpuUsageCircularBufferSize = CPU_UTIL_ARRAY_DEFAULT_SIZE;
189
194
else
190
195
_cpuUsageCircularBufferSize = TR::Options::_cpuUsageCircularBufferSize;
191
-
196
+
192
197
// Allocate the memory for the buffer
193
- _cpuUsageCircularBuffer =
194
- (CpuUsageCircularBuffer *)TR_PersistentMemory::jitPersistentAlloc (sizeof (CpuUsageCircularBuffer)*_cpuUsageCircularBufferSize);
195
-
198
+ _cpuUsageCircularBuffer =
199
+ (CpuUsageCircularBuffer *)TR_PersistentMemory::jitPersistentAlloc (sizeof (CpuUsageCircularBuffer)*_cpuUsageCircularBufferSize);
200
+
196
201
// Since this happens at bootstrap, if this fails, disable and return
197
202
if (!_cpuUsageCircularBuffer)
198
203
{
199
204
_isCpuUsageCircularBufferFunctional = false ;
200
205
return ;
201
206
}
202
-
207
+
203
208
// Initialize the buffer; no need to initialize the _sampleSystemCpu and _sampleJvmCpu
204
209
// fields since we can just check if _timeStamp equals 0
205
210
for (int32_t i = 0 ; i < _cpuUsageCircularBufferSize; i++)
@@ -223,24 +228,24 @@ CpuSelfThreadUtilization::CpuSelfThreadUtilization(TR::PersistentInfo *persisten
223
228
_isFunctional(true ) // optimistic
224
229
{
225
230
_lowResolutionClockAtLastUpdate = _persistentInfo->getElapsedTime ();
226
- _clockTimeAtLastUpdate = getCrtTimeNs ();
231
+ _clockTimeAtLastUpdate = getCrtTimeNs ();
227
232
_cpuTimeAtLastUpdate = 0 ; // getCpuTimeNow(); The constructor might not be called by the compilation thread
228
- }
233
+ }
229
234
230
- void CpuSelfThreadUtilization::setAsUnfunctional ()
231
- {
235
+ void CpuSelfThreadUtilization::setAsUnfunctional ()
236
+ {
232
237
_isFunctional = false ;
233
238
// set an invalid value which sometimes may obviate the need to test _isFunctional
234
239
_cpuTimeDuringLastInterval = _cpuTimeDuringSecondLastInterval = _cpuTimeAtLastUpdate = -1 ;
235
240
_lastCpuUtil = _secondLastCpuUtil = - 1 ;
236
241
// TODO: place a VM style trace point
237
- }
242
+ }
238
243
239
244
bool CpuSelfThreadUtilization::update () // return true if an update was performed
240
245
{
241
246
if (!_isFunctional)
242
247
return false ;
243
- // Refuse to update if not enough time has passed;
248
+ // Refuse to update if not enough time has passed;
244
249
// use the lower resolution time to avoid overhead
245
250
if ((_persistentInfo->getElapsedTime () - _lowResolutionClockAtLastUpdate)*1000000 < _minMeasurementIntervalLength)
246
251
return false ;
0 commit comments