Book a Demo!
CoCalc Logo Icon
StoreFeaturesDocsShareSupportNewsAboutPoliciesSign UpSign In
PojavLauncherTeam
GitHub Repository: PojavLauncherTeam/openj9
Path: blob/master/runtime/gc_verbose_handler_realtime/VerboseHandlerOutputRealtime.cpp
5985 views
1
/*******************************************************************************
2
* Copyright (c) 1991, 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
#include "VerboseHandlerOutputRealtime.hpp"
24
25
#include "CycleState.hpp"
26
#include "EnvironmentBase.hpp"
27
#include "GCExtensions.hpp"
28
#include "GCExtensionsBase.hpp"
29
#include "Heap.hpp"
30
#include "VerboseBuffer.hpp"
31
#include "VerboseHandlerRealtime.hpp"
32
#include "VerboseManager.hpp"
33
#include "VerboseWriterChain.hpp"
34
#include "VerboseHandlerJava.hpp"
35
36
#include "gcutils.h"
37
#include "mmhook.h"
38
#include "mmprivatehook.h"
39
40
MM_VerboseHandlerOutput *
41
MM_VerboseHandlerOutputRealtime::newInstance(MM_EnvironmentBase *env, MM_VerboseManager *manager)
42
{
43
MM_GCExtensions* extensions = MM_GCExtensions::getExtensions(env->getOmrVM());
44
45
MM_VerboseHandlerOutputRealtime *verboseHandlerOutput = (MM_VerboseHandlerOutputRealtime *)extensions->getForge()->allocate(sizeof(MM_VerboseHandlerOutputRealtime), MM_AllocationCategory::FIXED, J9_GET_CALLSITE());
46
if (NULL != verboseHandlerOutput) {
47
new(verboseHandlerOutput) MM_VerboseHandlerOutputRealtime(extensions);
48
if(!verboseHandlerOutput->initialize(env, manager)) {
49
verboseHandlerOutput->kill(env);
50
verboseHandlerOutput = NULL;
51
}
52
}
53
return verboseHandlerOutput;
54
}
55
56
bool
57
MM_VerboseHandlerOutputRealtime::initialize(MM_EnvironmentBase *env, MM_VerboseManager *manager)
58
{
59
PORT_ACCESS_FROM_ENVIRONMENT(env);
60
_verboseInitTimeStamp = j9time_hires_clock();
61
bool initSuccess = MM_VerboseHandlerOutput::initialize(env, manager);
62
63
_mmHooks = J9_HOOK_INTERFACE(MM_GCExtensions::getExtensions(_extensions)->hookInterface);
64
65
return initSuccess;
66
}
67
68
void
69
MM_VerboseHandlerOutputRealtime::tearDown(MM_EnvironmentBase *env)
70
{
71
MM_VerboseHandlerOutput::tearDown(env);
72
}
73
74
void
75
MM_VerboseHandlerOutputRealtime::enableVerbose()
76
{
77
MM_VerboseHandlerOutput::enableVerbose();
78
79
/* Cycle */
80
(*_mmOmrHooks)->J9HookRegisterWithCallSite(_mmOmrHooks, J9HOOK_MM_OMR_GC_CYCLE_START, verboseHandlerCycleStart, OMR_GET_CALLSITE(), (void *)this);
81
(*_mmPrivateHooks)->J9HookRegisterWithCallSite(_mmPrivateHooks, J9HOOK_MM_PRIVATE_GC_POST_CYCLE_END, verboseHandlerCycleEnd, OMR_GET_CALLSITE(), (void *)this);
82
83
/* trigger */
84
(*_mmPrivateHooks)->J9HookRegisterWithCallSite(_mmPrivateHooks, J9HOOK_MM_PRIVATE_METRONOME_TRIGGER_START, verboseHandlerTriggerStart, OMR_GET_CALLSITE(), (void *)this);
85
(*_mmPrivateHooks)->J9HookRegisterWithCallSite(_mmPrivateHooks, J9HOOK_MM_PRIVATE_METRONOME_TRIGGER_END, verboseHandlerTriggerEnd, OMR_GET_CALLSITE(), (void *)this);
86
87
/* increment */
88
(*_mmPrivateHooks)->J9HookRegisterWithCallSite(_mmPrivateHooks, J9HOOK_MM_PRIVATE_METRONOME_INCREMENT_START, verboseHandlerIncrementStart, OMR_GET_CALLSITE(), (void *)this);
89
(*_mmPrivateHooks)->J9HookRegisterWithCallSite(_mmPrivateHooks, J9HOOK_MM_PRIVATE_METRONOME_INCREMENT_END, verboseHandlerIncrementEnd, OMR_GET_CALLSITE(), (void *)this);
90
91
/* sync gc */
92
(*_mmPrivateHooks)->J9HookRegisterWithCallSite(_mmPrivateHooks, J9HOOK_MM_PRIVATE_METRONOME_SYNCHRONOUS_GC_START, verboseHandlerSyncGCStart, OMR_GET_CALLSITE(), (void *)this);
93
(*_mmPrivateHooks)->J9HookRegisterWithCallSite(_mmPrivateHooks, J9HOOK_MM_PRIVATE_METRONOME_SYNCHRONOUS_GC_END, verboseHandlerSyncGCEnd, OMR_GET_CALLSITE(), (void *)this);
94
95
/* mark, class unload, sweep phases */
96
(*_mmPrivateHooks)->J9HookRegisterWithCallSite(_mmPrivateHooks, J9HOOK_MM_PRIVATE_MARK_START, verboseHandlerMarkStart, OMR_GET_CALLSITE(), (void *)this);
97
(*_mmPrivateHooks)->J9HookRegisterWithCallSite(_mmPrivateHooks, J9HOOK_MM_PRIVATE_MARK_END, verboseHandlerMarkEnd, OMR_GET_CALLSITE(), (void *)this);
98
99
(*_mmPrivateHooks)->J9HookRegisterWithCallSite(_mmPrivateHooks, J9HOOK_MM_PRIVATE_SWEEP_START, verboseHandlerSweepStart, OMR_GET_CALLSITE(), (void *)this);
100
(*_mmPrivateHooks)->J9HookRegisterWithCallSite(_mmPrivateHooks, J9HOOK_MM_PRIVATE_SWEEP_END, verboseHandlerSweepEnd, OMR_GET_CALLSITE(), (void *)this);
101
#if defined(J9VM_GC_DYNAMIC_CLASS_UNLOADING)
102
(*_mmPrivateHooks)->J9HookRegisterWithCallSite(_mmPrivateHooks, J9HOOK_MM_PRIVATE_CLASS_UNLOADING_START, verboseHandlerClassUnloadingStart, OMR_GET_CALLSITE(), (void *)this);
103
(*_mmHooks)->J9HookRegisterWithCallSite(_mmHooks, J9HOOK_MM_CLASS_UNLOADING_END, verboseHandlerClassUnloadingEnd, OMR_GET_CALLSITE(), (void *)this);
104
#endif /* defined(J9VM_GC_DYNAMIC_CLASS_UNLOADING) */
105
106
(*_mmPrivateHooks)->J9HookRegisterWithCallSite(_mmPrivateHooks, J9HOOK_MM_PRIVATE_OUT_OF_MEMORY, verboseHandlerOutOFMemory, OMR_GET_CALLSITE(), (void *)this);
107
(*_mmPrivateHooks)->J9HookRegisterWithCallSite(_mmPrivateHooks, J9HOOK_MM_PRIVATE_UTILIZATION_TRACKER_OVERFLOW, verboseHandlerUtilTrackerOverflow, OMR_GET_CALLSITE(), (void *)this);
108
(*_mmPrivateHooks)->J9HookRegisterWithCallSite(_mmPrivateHooks, J9HOOK_MM_PRIVATE_NON_MONOTONIC_TIME, verboseHandlerNonMonotonicTime, OMR_GET_CALLSITE(), (void *)this);
109
}
110
111
void
112
MM_VerboseHandlerOutputRealtime::disableVerbose()
113
{
114
MM_VerboseHandlerOutput::disableVerbose();
115
116
/* Cycle */
117
(*_mmOmrHooks)->J9HookUnregister(_mmOmrHooks, J9HOOK_MM_OMR_GC_CYCLE_START, verboseHandlerCycleStart, NULL);
118
(*_mmPrivateHooks)->J9HookUnregister(_mmPrivateHooks, J9HOOK_MM_PRIVATE_GC_POST_CYCLE_END, verboseHandlerCycleEnd, NULL);
119
120
/* trigger */
121
(*_mmPrivateHooks)->J9HookUnregister(_mmPrivateHooks, J9HOOK_MM_PRIVATE_METRONOME_TRIGGER_START, verboseHandlerTriggerStart, NULL);
122
(*_mmPrivateHooks)->J9HookUnregister(_mmPrivateHooks, J9HOOK_MM_PRIVATE_METRONOME_TRIGGER_END, verboseHandlerTriggerEnd, NULL);
123
124
/* increment */
125
(*_mmPrivateHooks)->J9HookUnregister(_mmPrivateHooks, J9HOOK_MM_PRIVATE_METRONOME_INCREMENT_START, verboseHandlerIncrementStart, NULL);
126
(*_mmPrivateHooks)->J9HookUnregister(_mmPrivateHooks, J9HOOK_MM_PRIVATE_METRONOME_INCREMENT_END, verboseHandlerIncrementEnd, NULL);
127
128
/* sync gc */
129
(*_mmPrivateHooks)->J9HookUnregister(_mmPrivateHooks, J9HOOK_MM_PRIVATE_METRONOME_SYNCHRONOUS_GC_START, verboseHandlerSyncGCStart, NULL);
130
(*_mmPrivateHooks)->J9HookUnregister(_mmPrivateHooks, J9HOOK_MM_PRIVATE_METRONOME_SYNCHRONOUS_GC_END, verboseHandlerSyncGCEnd, NULL);
131
132
/* mark, class unload, sweep phases */
133
(*_mmPrivateHooks)->J9HookUnregister(_mmPrivateHooks, J9HOOK_MM_PRIVATE_MARK_START, verboseHandlerMarkStart, NULL);
134
(*_mmPrivateHooks)->J9HookUnregister(_mmPrivateHooks, J9HOOK_MM_PRIVATE_MARK_END, verboseHandlerMarkEnd, NULL);
135
(*_mmPrivateHooks)->J9HookUnregister(_mmPrivateHooks, J9HOOK_MM_PRIVATE_SWEEP_START, verboseHandlerSweepStart, NULL);
136
(*_mmPrivateHooks)->J9HookUnregister(_mmPrivateHooks, J9HOOK_MM_PRIVATE_SWEEP_END, verboseHandlerSweepEnd, NULL);
137
#if defined(J9VM_GC_DYNAMIC_CLASS_UNLOADING)
138
(*_mmPrivateHooks)->J9HookUnregister(_mmPrivateHooks, J9HOOK_MM_PRIVATE_CLASS_UNLOADING_START, verboseHandlerClassUnloadingStart, NULL);
139
(*_mmHooks)->J9HookUnregister(_mmHooks, J9HOOK_MM_CLASS_UNLOADING_END, verboseHandlerClassUnloadingEnd, NULL);
140
#endif /* defined(J9VM_GC_DYNAMIC_CLASS_UNLOADING) */
141
142
(*_mmPrivateHooks)->J9HookUnregister(_mmPrivateHooks, J9HOOK_MM_PRIVATE_OUT_OF_MEMORY, verboseHandlerOutOFMemory, NULL);
143
(*_mmPrivateHooks)->J9HookUnregister(_mmPrivateHooks, J9HOOK_MM_PRIVATE_UTILIZATION_TRACKER_OVERFLOW, verboseHandlerUtilTrackerOverflow, NULL);
144
(*_mmPrivateHooks)->J9HookUnregister(_mmPrivateHooks, J9HOOK_MM_PRIVATE_NON_MONOTONIC_TIME, verboseHandlerNonMonotonicTime, NULL);
145
}
146
147
bool
148
MM_VerboseHandlerOutputRealtime::getThreadName(char *buf, UDATA bufLen, OMR_VMThread *vmThread)
149
{
150
return MM_VerboseHandlerJava::getThreadName(buf,bufLen,vmThread);
151
}
152
153
void
154
MM_VerboseHandlerOutputRealtime::writeVmArgs(MM_EnvironmentBase* env, MM_VerboseBuffer* buffer)
155
{
156
MM_VerboseHandlerJava::writeVmArgs(env, buffer, static_cast<J9JavaVM*>(_omrVM->_language_vm));
157
}
158
159
const char *
160
MM_VerboseHandlerOutputRealtime::getCycleType(UDATA type)
161
{
162
const char* cycleType = NULL;
163
switch (type) {
164
case OMR_GC_CYCLE_TYPE_DEFAULT:
165
cycleType = "default";
166
break;
167
case OMR_GC_CYCLE_TYPE_GLOBAL:
168
cycleType = "global";
169
break;
170
default:
171
cycleType = "unknown";
172
break;
173
}
174
175
return cycleType;
176
}
177
178
void
179
MM_VerboseHandlerOutputRealtime::outputInitializedInnerStanza(MM_EnvironmentBase *env, MM_VerboseBuffer *buffer){
180
MM_GCExtensionsBase *extensions = env->getExtensions();
181
outputInitializedRegion(env, buffer);
182
buffer->formatAndOutput(env, 1, "<metronome>");
183
buffer->formatAndOutput(env, 2, "<attribute name=\"beatsPerMeasure\" value=\"%zu\" />", extensions->beatMicro);
184
buffer->formatAndOutput(env, 2, "<attribute name=\"timeInterval\" value=\"%zu\" />", extensions->timeWindowMicro);
185
buffer->formatAndOutput(env, 2, "<attribute name=\"targetUtilization\" value=\"%zu\" />", extensions->targetUtilizationPercentage);
186
buffer->formatAndOutput(env, 2, "<attribute name=\"trigger\" value=\"0x%zx\" />", extensions->gcTrigger);
187
buffer->formatAndOutput(env, 2, "<attribute name=\"headRoom\" value=\"0x%zx\" />", extensions->headRoom);
188
buffer->formatAndOutput(env, 1, "</metronome>");
189
}
190
191
void
192
MM_VerboseHandlerOutputRealtime::handleEvent(MM_MetronomeIncrementStartEvent* eventData)
193
{
194
/* if we are in a sync gc cycle, do nothing here and let the syncgc stanza handle things */
195
if (!_syncGCTriggered) {
196
if (0 == _heartbeatStartTime) {
197
_heartbeatStartTime = eventData->timestamp;
198
}
199
_incrementStartTime = eventData->timestamp;
200
_incrementCount++;
201
_totalExclusiveAccessTime += eventData->exclusiveAccessTime;
202
_maxExclusiveAccessTime = OMR_MAX(eventData->exclusiveAccessTime, _maxExclusiveAccessTime);
203
_minExclusiveAccessTime = OMR_MIN(eventData->exclusiveAccessTime, _minExclusiveAccessTime);
204
} else {
205
/* if we are in a sync GC cycle, only collect the exclusive access time */
206
_syncGCExclusiveAccessTime = eventData->exclusiveAccessTime;
207
}
208
}
209
210
void
211
MM_VerboseHandlerOutputRealtime::writeHeartbeatData(MM_EnvironmentBase* env, U_64 timestamp)
212
{
213
/* if we are in a sync gc cycle OR if there is no heartbeat data, nothing to do */
214
if (!_syncGCTriggered && 0 != _heartbeatStartTime) {
215
MM_VerboseWriterChain* writer = _manager->getWriterChain();
216
PORT_ACCESS_FROM_ENVIRONMENT(env);
217
218
char tagTemplate[200];
219
getTagTemplate(tagTemplate, sizeof(tagTemplate), _manager->getIdAndIncrement(), "heartbeat", env->_cycleState->_verboseContextID, j9time_current_time_millis());
220
enterAtomicReportingBlock();
221
writer->formatAndOutput(env, 0, "<gc-op %s>", tagTemplate);
222
223
U_64 maxQuantaTime = j9time_hires_delta(_heartbeatStartTime, _maxIncrementStartTime, J9PORT_TIME_DELTA_IN_MICROSECONDS);
224
U_64 meanIncrementTime = _totalIncrementTime / _incrementCount;
225
const char *gcPhase = NULL;
226
if(incrementStartsInPreviousGCPhase()) {
227
gcPhase = getGCPhaseAsString(_previousGCPhase);
228
_previousGCPhase = _gcPhase;
229
} else {
230
gcPhase = getGCPhaseAsString(_gcPhase);
231
}
232
writer->formatAndOutput(
233
env, 1 /*indent*/,
234
"<quanta quantumCount=\"%zu\" quantumType=\"%s\" minTimeMs=\"%llu.%03.3llu\" meanTimeMs=\"%llu.%03.3llu\" maxTimeMs=\"%llu.%03.3llu\" maxTimestampMs=\"%llu.%03.3llu\" />",
235
_incrementCount,
236
gcPhase,
237
_minIncrementTime / 1000,
238
_minIncrementTime % 1000,
239
meanIncrementTime / 1000,
240
meanIncrementTime % 1000,
241
_maxIncrementTime / 1000,
242
_maxIncrementTime % 1000,
243
maxQuantaTime / 1000,
244
maxQuantaTime % 1000
245
);
246
247
U_64 meanExclusiveAccessTime = _totalExclusiveAccessTime / _incrementCount;
248
writer->formatAndOutput(
249
env, 1 /*indent*/,
250
"<exclusiveaccess-info minTimeMs=\"%llu.%03.3llu\" meanTimeMs=\"%llu.%03.3llu\" maxTimeMs=\"%llu.%03.3llu\" />",
251
_minExclusiveAccessTime / 1000,
252
_minExclusiveAccessTime % 1000,
253
meanExclusiveAccessTime / 1000,
254
meanExclusiveAccessTime % 1000,
255
_maxExclusiveAccessTime / 1000,
256
_maxExclusiveAccessTime % 1000
257
);
258
259
if ((0 != _classesUnloadedTotal) || (0 != _classLoadersUnloadedTotal)) {
260
writer->formatAndOutput(
261
env, 1 /*indent*/,
262
"<classunload-info classloadersunloaded=\"%zu\" classesunloaded=\"%zu\" anonymousclassesunloaded=\"%zu\" />",
263
_classLoadersUnloadedTotal,
264
_classesUnloadedTotal,
265
_anonymousClassesUnloadedTotal
266
);
267
}
268
269
if (0 != _softReferenceClearCountTotal) {
270
writer->formatAndOutput(
271
env, 1, "<references type=\"soft\" cleared=\"%zu\" dynamicThreshold=\"%zu\" maxThreshold=\"%zu\" />",
272
_weakReferenceClearCountTotal,
273
_dynamicSoftReferenceThreshold,
274
_softReferenceThreshold
275
);
276
}
277
if (0 != _weakReferenceClearCountTotal) {
278
writer->formatAndOutput(env, 1, "<references type=\"weak\" cleared=\"%zu\" />", _weakReferenceClearCountTotal);
279
}
280
if (0 != _phantomReferenceClearCountTotal) {
281
writer->formatAndOutput(env, 1, "<references type=\"phantom\" cleared=\"%zu\" />", _phantomReferenceClearCountTotal);
282
}
283
284
if (0 != _finalizableCountTotal) {
285
writer->formatAndOutput(env, 1, "<finalization enqueued=\"%zu\" />", _finalizableCountTotal);
286
}
287
288
if ((0 != _workPacketOverflowCountTotal) || (0 != _objectOverflowCountTotal)) {
289
writer->formatAndOutput(
290
env, 1 /*indent*/,
291
"<work-packet-overflow packetCount=\"%zu\" directObjectCount=\"%zu\" />",
292
_workPacketOverflowCountTotal,
293
_objectOverflowCountTotal
294
);
295
}
296
297
if (0 != _nonDeterministicSweepTotal) {
298
writer->formatAndOutput(
299
env, 1 /*indent*/,
300
"<nondeterministic-sweep maxTimeMs=\"%llu.%03.3llu\" totalRegions=\"%zu\" maxRegions=\"%zu\" />",
301
_nonDeterministicSweepDelayMax / 1000,
302
_nonDeterministicSweepDelayMax % 1000,
303
_nonDeterministicSweepTotal,
304
_nonDeterministicSweepConsecutiveMax
305
);
306
}
307
308
U_64 meanHeapFree = _totalHeapFree / _incrementCount;
309
writer->formatAndOutput(
310
env, 1 /*indent*/,
311
"<free-mem type=\"heap\" minBytes=\"%llu\" meanBytes=\"%llu\" maxBytes=\"%llu\" />",
312
_minHeapFree,
313
meanHeapFree,
314
_maxHeapFree
315
);
316
317
writer->formatAndOutput(
318
env, 1 /*indent*/,
319
"<thread-priority maxPriority=\"%zu\" minPriority=\"%zu\" />",
320
_maxStartPriority,
321
_minStartPriority
322
);
323
324
writer->formatAndOutput(env, 0, "</gc-op>");
325
writer->flush(env);
326
exitAtomicReportingBlock();
327
}
328
}
329
330
void
331
MM_VerboseHandlerOutputRealtime::writeHeartbeatDataAndResetHeartbeatStats(MM_EnvironmentBase* env, U_64 timestamp)
332
{
333
writeHeartbeatData(env, timestamp);
334
resetHeartbeatStats();
335
}
336
337
void
338
MM_VerboseHandlerOutputRealtime::handleEvent(MM_MetronomeIncrementEndEvent* eventData)
339
{
340
/* process only if we are in a heartbeat */
341
if (0 != _heartbeatStartTime) {
342
MM_EnvironmentBase* env = MM_EnvironmentBase::getEnvironment(eventData->currentThread);
343
MM_GCExtensions* extensions = MM_GCExtensions::getExtensions(env->getOmrVM());
344
345
PORT_ACCESS_FROM_ENVIRONMENT(env);
346
347
U_64 incrementTime = j9time_hires_delta(_incrementStartTime, eventData->timestamp, J9PORT_TIME_DELTA_IN_MICROSECONDS);
348
_totalIncrementTime += incrementTime;
349
if (incrementTime > _maxIncrementTime) {
350
_maxIncrementTime = incrementTime;
351
_maxIncrementStartTime = _incrementStartTime;
352
}
353
/* reset increment start time */
354
_incrementStartTime = 0;
355
_minIncrementTime = OMR_MIN(incrementTime, _minIncrementTime);
356
357
_classLoadersUnloadedTotal += extensions->globalGCStats.metronomeStats.classLoaderUnloadedCount;
358
_classesUnloadedTotal += extensions->globalGCStats.metronomeStats.classesUnloadedCount;
359
_anonymousClassesUnloadedTotal += extensions->globalGCStats.metronomeStats.anonymousClassesUnloadedCount;
360
361
_weakReferenceClearCountTotal += extensions->markJavaStats._weakReferenceStats._cleared;
362
_softReferenceClearCountTotal += extensions->markJavaStats._softReferenceStats._cleared;
363
_softReferenceThreshold = extensions->getMaxSoftReferenceAge();
364
_dynamicSoftReferenceThreshold = extensions->getDynamicMaxSoftReferenceAge();
365
_phantomReferenceClearCountTotal += extensions->markJavaStats._phantomReferenceStats._cleared;
366
367
_finalizableCountTotal += extensions->markJavaStats._unfinalizedEnqueued;
368
369
_workPacketOverflowCountTotal += extensions->globalGCStats.metronomeStats.getWorkPacketOverflowCount();
370
_objectOverflowCountTotal += extensions->globalGCStats.metronomeStats.getObjectOverflowCount();
371
372
_nonDeterministicSweepTotal += extensions->globalGCStats.metronomeStats.nonDeterministicSweepCount;
373
_nonDeterministicSweepConsecutiveMax = OMR_MAX(_nonDeterministicSweepConsecutiveMax, extensions->globalGCStats.metronomeStats.nonDeterministicSweepConsecutive);
374
_nonDeterministicSweepDelayMax = OMR_MAX(_nonDeterministicSweepDelayMax, extensions->globalGCStats.metronomeStats.nonDeterministicSweepDelay);
375
376
_maxHeapFree = OMR_MAX(_maxHeapFree, _extensions->heap->getApproximateActiveFreeMemorySize());
377
_totalHeapFree += _extensions->heap->getApproximateActiveFreeMemorySize();
378
_minHeapFree = OMR_MIN(_minHeapFree, _extensions->heap->getApproximateActiveFreeMemorySize());
379
380
UDATA startPriority = omrthread_get_priority(eventData->currentThread->_os_thread);
381
_maxStartPriority = OMR_MAX(_maxStartPriority, startPriority);
382
_minStartPriority = OMR_MIN(_minStartPriority, startPriority);
383
384
U_64 timeSinceHeartbeatStart = j9time_hires_delta(_heartbeatStartTime, eventData->timestamp, J9PORT_TIME_DELTA_IN_MICROSECONDS);
385
if (((timeSinceHeartbeatStart / 1000) >= extensions->verbosegcCycleTime)
386
|| (incrementStartsInPreviousGCPhase())) {
387
writeHeartbeatDataAndResetHeartbeatStats(env, eventData->timestamp);
388
}
389
}
390
}
391
392
void
393
MM_VerboseHandlerOutputRealtime::handleEvent(MM_MetronomeSynchronousGCStartEvent* eventData)
394
{
395
/* we hit a sync GC, flush heartbeat data collected so far */
396
writeHeartbeatDataAndResetHeartbeatStats(MM_EnvironmentBase::getEnvironment(eventData->currentThread), eventData->timestamp);
397
398
_syncGCTriggered = true;
399
_syncGCStartTime = eventData->timestamp;
400
_syncGCReason = (GCReason)eventData->reason;
401
_syncGCReasonParameter = eventData->reasonParameter;
402
_syncGCStartHeapFree = eventData->heapFree;
403
_syncGCStartImmortalFree = eventData->immortalFree;
404
_syncGCStartClassLoadersUnloaded = eventData->classLoadersUnloaded;
405
_syncGCStartClassesUnloaded = eventData->classesUnloaded;
406
_syncGCStartAnonymousClassesUnloaded = eventData->anonymousClassesUnloaded;
407
}
408
409
void
410
MM_VerboseHandlerOutputRealtime::handleEvent(MM_MetronomeSynchronousGCEndEvent* eventData)
411
{
412
MM_EnvironmentBase* env = MM_EnvironmentBase::getEnvironment(eventData->currentThread);
413
PORT_ACCESS_FROM_ENVIRONMENT(env);
414
char tagTemplate[200];
415
MM_VerboseWriterChain* writer = _manager->getWriterChain();
416
enterAtomicReportingBlock();
417
418
U_64 syncGCTimeDuration = 0;
419
bool deltaTimeSuccess = getTimeDeltaInMicroSeconds(&syncGCTimeDuration, _syncGCStartTime, eventData->timestamp);
420
421
getTagTemplate(tagTemplate, sizeof(tagTemplate), _manager->getIdAndIncrement(), "syncgc", env->_cycleState->_verboseContextID, syncGCTimeDuration, j9time_current_time_millis());
422
423
if (!deltaTimeSuccess) {
424
writer->formatAndOutput(env, 0, "<warning details=\"clock error detected, following timing may be inaccurate\" />");
425
}
426
427
writer->formatAndOutput(env, 0, "<gc-op %s>", tagTemplate);
428
429
const char *hookReason = getGCReasonAsString(_syncGCReason);
430
if (_syncGCReason == OUT_OF_MEMORY_TRIGGER) {
431
writer->formatAndOutput(
432
env, 1 /*indent*/,
433
"<syncgc-info reason=\"%s\" totalBytesRequested=\"%zu\" exclusiveaccessTimeMs=\"%llu.%03.3llu\" threadPriority=\"%zu\" />",
434
hookReason,
435
_syncGCReasonParameter,
436
_syncGCExclusiveAccessTime / 1000,
437
_syncGCExclusiveAccessTime % 1000,
438
omrthread_get_priority(eventData->currentThread->_os_thread)
439
);
440
} else {
441
writer->formatAndOutput(
442
env, 1 /*indent*/,
443
"<syncgc-info reason=\"%s\" exclusiveaccessTimeMs=\"%llu.%03.3llu\" threadPriority=\"%zu\" />",
444
hookReason,
445
_syncGCExclusiveAccessTime / 1000,
446
_syncGCExclusiveAccessTime % 1000,
447
omrthread_get_priority(eventData->currentThread->_os_thread)
448
);
449
}
450
451
writer->formatAndOutput(env, 1, "<free-mem-delta type=\"heap\" bytesBefore=\"%zu\" bytesAfter=\"%zu\" />", _syncGCStartHeapFree, eventData->heapFree);
452
453
if ((0 != eventData->workPacketOverflowCount) || (0 != eventData->objectOverflowCount)) {
454
writer->formatAndOutput(
455
env, 1 /*indent*/,
456
"<work-packet-overflow packetCount=\"%zu\" directObjectCount=\"%zu\" />",
457
eventData->workPacketOverflowCount,
458
eventData->objectOverflowCount
459
);
460
}
461
462
if ((_syncGCStartClassesUnloaded != eventData->classesUnloaded) || (_syncGCStartClassLoadersUnloaded != eventData->classLoadersUnloaded)) {
463
writer->formatAndOutput(
464
env, 1 /*indent*/,
465
"<classunload-info classloadersunloaded=\"%zu\" classesunloaded=\"%zu\" anonymousclassesunloaded=\"%zu\" />",
466
eventData->classLoadersUnloaded - _syncGCStartClassLoadersUnloaded,
467
eventData->classesUnloaded - _syncGCStartClassesUnloaded,
468
eventData->anonymousClassesUnloaded - _syncGCStartAnonymousClassesUnloaded
469
);
470
}
471
472
if (0 != eventData->softReferenceClearCount) {
473
writer->formatAndOutput(
474
env, 1,
475
"<references type=\"soft\" cleared=\"%zu\" dynamicThreshold=\"%zu\" maxThreshold=\"%zu\" />",
476
eventData->softReferenceClearCount,
477
eventData->dynamicSoftReferenceThreshold,
478
eventData->softReferenceThreshold
479
);
480
}
481
if (0 != eventData->weakReferenceClearCount) {
482
writer->formatAndOutput(env, 1, "<references type=\"weak\" cleared=\"%zu\" />",eventData->weakReferenceClearCount);
483
}
484
if (0 != eventData->phantomReferenceClearCount) {
485
writer->formatAndOutput(env, 1, "<references type=\"phantom\" cleared=\"%zu\" />",eventData->phantomReferenceClearCount);
486
}
487
488
if (0 != eventData->finalizableCount) {
489
writer->formatAndOutput(env, 1,"<finalization enqueued=\"%zu\" />", eventData->finalizableCount);
490
}
491
492
writer->formatAndOutput(env, 0, "</gc-op>");
493
writer->flush(env);
494
exitAtomicReportingBlock();
495
496
resetSyncGCStats();
497
}
498
499
void
500
MM_VerboseHandlerOutputRealtime::handleCycleStart(J9HookInterface** hook, UDATA eventNum, void* eventData)
501
{
502
MM_VerboseHandlerOutput::handleCycleStart(hook, eventNum, eventData);
503
/* set the gc phase to mark at the start of the cycle */
504
_previousGCPhase = _gcPhase = PRE_COLLECT;
505
}
506
507
void
508
MM_VerboseHandlerOutputRealtime::handleCycleEnd(J9HookInterface** hook, UDATA eventNum, void* eventData)
509
{
510
MM_GCPostCycleEndEvent* cycleEndEvent = (MM_GCPostCycleEndEvent*)eventData;
511
writeHeartbeatDataAndResetHeartbeatStats(MM_EnvironmentBase::getEnvironment(cycleEndEvent->currentThread), cycleEndEvent->timestamp);
512
MM_VerboseHandlerOutput::handleCycleEnd(hook, eventNum, eventData);
513
/* set the gc phase to inactive at the end of the cycle */
514
_previousGCPhase = _gcPhase = INACTIVE;
515
}
516
517
void
518
MM_VerboseHandlerOutputRealtime::handleEvent(MM_MarkStartEvent* eventData)
519
{
520
_previousGCPhase = _gcPhase = MARK;
521
}
522
523
void
524
MM_VerboseHandlerOutputRealtime::handleEvent(MM_MarkEndEvent* eventData)
525
{
526
_previousGCPhase = MARK;
527
}
528
529
void
530
MM_VerboseHandlerOutputRealtime::handleEvent(MM_ClassUnloadingStartEvent* eventData)
531
{
532
_gcPhase = CLASS_UNLOAD;
533
}
534
535
void
536
MM_VerboseHandlerOutputRealtime::handleEvent(MM_ClassUnloadingEndEvent* eventData)
537
{
538
if (!incrementStartsInPreviousGCPhase()) {
539
_previousGCPhase = CLASS_UNLOAD;
540
}
541
}
542
543
void
544
MM_VerboseHandlerOutputRealtime::handleEvent(MM_SweepStartEvent* eventData)
545
{
546
_gcPhase = SWEEP;
547
}
548
549
void
550
MM_VerboseHandlerOutputRealtime::handleEvent(MM_SweepEndEvent* eventData)
551
{
552
if (!incrementStartsInPreviousGCPhase()) {
553
_previousGCPhase = SWEEP;
554
}
555
_gcPhase = POST_COLLECT;
556
}
557
558
void
559
MM_VerboseHandlerOutputRealtime::handleEvent(MM_OutOfMemoryEvent* eventData)
560
{
561
MM_EnvironmentBase* env = MM_EnvironmentBase::getEnvironment(eventData->currentThread);
562
MM_VerboseWriterChain* writer = _manager->getWriterChain();
563
PORT_ACCESS_FROM_ENVIRONMENT(env);
564
char tagTemplate[200];
565
getTagTemplate(tagTemplate, sizeof(tagTemplate), _manager->getIdAndIncrement(), j9time_current_time_millis());
566
567
enterAtomicReportingBlock();
568
writer->formatAndOutput(
569
env, 0 /*indent*/,
570
"<out-of-memory %s memorySpaceName=\"%s\" memorySpaceAddress=\"%p\" />",
571
tagTemplate,
572
eventData->memorySpaceString,
573
eventData->memorySpace
574
);
575
writer->flush(env);
576
exitAtomicReportingBlock();
577
}
578
579
void
580
MM_VerboseHandlerOutputRealtime::handleEvent(MM_UtilizationTrackerOverflowEvent* eventData)
581
{
582
MM_EnvironmentBase* env = MM_EnvironmentBase::getEnvironment(eventData->currentThread);
583
writeHeartbeatDataAndResetHeartbeatStats(env, eventData->timestamp);
584
MM_VerboseWriterChain* writer = _manager->getWriterChain();
585
PORT_ACCESS_FROM_ENVIRONMENT(env);
586
char tagTemplate[200];
587
getTagTemplate(tagTemplate, sizeof(tagTemplate), _manager->getIdAndIncrement(), j9time_current_time_millis());
588
589
enterAtomicReportingBlock();
590
writer->formatAndOutput(
591
env, 0 /*indent*/,
592
"<utilization-tracker-overflow %s utilizationTrackerAddress=\"%p\" timeSliceDurationArrayAddress=\"%p\" timeSliceCursor=\"%zu\" />",
593
tagTemplate,
594
eventData->utilizationTrackerAddress,
595
eventData->timeSliceDurationArrayAddress,
596
eventData->timeSliceCursor
597
);
598
writer->flush(env);
599
exitAtomicReportingBlock();
600
}
601
602
void
603
MM_VerboseHandlerOutputRealtime::handleEvent(MM_NonMonotonicTimeEvent* eventData)
604
{
605
MM_EnvironmentBase* env = MM_EnvironmentBase::getEnvironment(eventData->currentThread);
606
writeHeartbeatDataAndResetHeartbeatStats(env, eventData->timestamp);
607
MM_VerboseWriterChain* writer = _manager->getWriterChain();
608
PORT_ACCESS_FROM_ENVIRONMENT(env);
609
char tagTemplate[200];
610
getTagTemplate(tagTemplate, sizeof(tagTemplate), _manager->getIdAndIncrement(), j9time_current_time_millis());
611
612
enterAtomicReportingBlock();
613
writer->formatAndOutput(env, 0, "<non-monotonic-time timerDescription=\"%s\" %s />", eventData->timerDesc, tagTemplate);
614
writer->flush(env);
615
exitAtomicReportingBlock();
616
}
617
618