Path: blob/master/runtime/gc_verbose_handler_realtime/VerboseHandlerOutputRealtime.cpp
5985 views
/*******************************************************************************1* Copyright (c) 1991, 2020 IBM Corp. and others2*3* This program and the accompanying materials are made available under4* the terms of the Eclipse Public License 2.0 which accompanies this5* distribution and is available at https://www.eclipse.org/legal/epl-2.0/6* or the Apache License, Version 2.0 which accompanies this distribution and7* is available at https://www.apache.org/licenses/LICENSE-2.0.8*9* This Source Code may also be made available under the following10* Secondary Licenses when the conditions for such availability set11* forth in the Eclipse Public License, v. 2.0 are satisfied: GNU12* General Public License, version 2 with the GNU Classpath13* Exception [1] and GNU General Public License, version 2 with the14* OpenJDK Assembly Exception [2].15*16* [1] https://www.gnu.org/software/classpath/license.html17* [2] http://openjdk.java.net/legal/assembly-exception.html18*19* 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-exception20*******************************************************************************/2122#include "VerboseHandlerOutputRealtime.hpp"2324#include "CycleState.hpp"25#include "EnvironmentBase.hpp"26#include "GCExtensions.hpp"27#include "GCExtensionsBase.hpp"28#include "Heap.hpp"29#include "VerboseBuffer.hpp"30#include "VerboseHandlerRealtime.hpp"31#include "VerboseManager.hpp"32#include "VerboseWriterChain.hpp"33#include "VerboseHandlerJava.hpp"3435#include "gcutils.h"36#include "mmhook.h"37#include "mmprivatehook.h"3839MM_VerboseHandlerOutput *40MM_VerboseHandlerOutputRealtime::newInstance(MM_EnvironmentBase *env, MM_VerboseManager *manager)41{42MM_GCExtensions* extensions = MM_GCExtensions::getExtensions(env->getOmrVM());4344MM_VerboseHandlerOutputRealtime *verboseHandlerOutput = (MM_VerboseHandlerOutputRealtime *)extensions->getForge()->allocate(sizeof(MM_VerboseHandlerOutputRealtime), MM_AllocationCategory::FIXED, J9_GET_CALLSITE());45if (NULL != verboseHandlerOutput) {46new(verboseHandlerOutput) MM_VerboseHandlerOutputRealtime(extensions);47if(!verboseHandlerOutput->initialize(env, manager)) {48verboseHandlerOutput->kill(env);49verboseHandlerOutput = NULL;50}51}52return verboseHandlerOutput;53}5455bool56MM_VerboseHandlerOutputRealtime::initialize(MM_EnvironmentBase *env, MM_VerboseManager *manager)57{58PORT_ACCESS_FROM_ENVIRONMENT(env);59_verboseInitTimeStamp = j9time_hires_clock();60bool initSuccess = MM_VerboseHandlerOutput::initialize(env, manager);6162_mmHooks = J9_HOOK_INTERFACE(MM_GCExtensions::getExtensions(_extensions)->hookInterface);6364return initSuccess;65}6667void68MM_VerboseHandlerOutputRealtime::tearDown(MM_EnvironmentBase *env)69{70MM_VerboseHandlerOutput::tearDown(env);71}7273void74MM_VerboseHandlerOutputRealtime::enableVerbose()75{76MM_VerboseHandlerOutput::enableVerbose();7778/* Cycle */79(*_mmOmrHooks)->J9HookRegisterWithCallSite(_mmOmrHooks, J9HOOK_MM_OMR_GC_CYCLE_START, verboseHandlerCycleStart, OMR_GET_CALLSITE(), (void *)this);80(*_mmPrivateHooks)->J9HookRegisterWithCallSite(_mmPrivateHooks, J9HOOK_MM_PRIVATE_GC_POST_CYCLE_END, verboseHandlerCycleEnd, OMR_GET_CALLSITE(), (void *)this);8182/* trigger */83(*_mmPrivateHooks)->J9HookRegisterWithCallSite(_mmPrivateHooks, J9HOOK_MM_PRIVATE_METRONOME_TRIGGER_START, verboseHandlerTriggerStart, OMR_GET_CALLSITE(), (void *)this);84(*_mmPrivateHooks)->J9HookRegisterWithCallSite(_mmPrivateHooks, J9HOOK_MM_PRIVATE_METRONOME_TRIGGER_END, verboseHandlerTriggerEnd, OMR_GET_CALLSITE(), (void *)this);8586/* increment */87(*_mmPrivateHooks)->J9HookRegisterWithCallSite(_mmPrivateHooks, J9HOOK_MM_PRIVATE_METRONOME_INCREMENT_START, verboseHandlerIncrementStart, OMR_GET_CALLSITE(), (void *)this);88(*_mmPrivateHooks)->J9HookRegisterWithCallSite(_mmPrivateHooks, J9HOOK_MM_PRIVATE_METRONOME_INCREMENT_END, verboseHandlerIncrementEnd, OMR_GET_CALLSITE(), (void *)this);8990/* sync gc */91(*_mmPrivateHooks)->J9HookRegisterWithCallSite(_mmPrivateHooks, J9HOOK_MM_PRIVATE_METRONOME_SYNCHRONOUS_GC_START, verboseHandlerSyncGCStart, OMR_GET_CALLSITE(), (void *)this);92(*_mmPrivateHooks)->J9HookRegisterWithCallSite(_mmPrivateHooks, J9HOOK_MM_PRIVATE_METRONOME_SYNCHRONOUS_GC_END, verboseHandlerSyncGCEnd, OMR_GET_CALLSITE(), (void *)this);9394/* mark, class unload, sweep phases */95(*_mmPrivateHooks)->J9HookRegisterWithCallSite(_mmPrivateHooks, J9HOOK_MM_PRIVATE_MARK_START, verboseHandlerMarkStart, OMR_GET_CALLSITE(), (void *)this);96(*_mmPrivateHooks)->J9HookRegisterWithCallSite(_mmPrivateHooks, J9HOOK_MM_PRIVATE_MARK_END, verboseHandlerMarkEnd, OMR_GET_CALLSITE(), (void *)this);9798(*_mmPrivateHooks)->J9HookRegisterWithCallSite(_mmPrivateHooks, J9HOOK_MM_PRIVATE_SWEEP_START, verboseHandlerSweepStart, OMR_GET_CALLSITE(), (void *)this);99(*_mmPrivateHooks)->J9HookRegisterWithCallSite(_mmPrivateHooks, J9HOOK_MM_PRIVATE_SWEEP_END, verboseHandlerSweepEnd, OMR_GET_CALLSITE(), (void *)this);100#if defined(J9VM_GC_DYNAMIC_CLASS_UNLOADING)101(*_mmPrivateHooks)->J9HookRegisterWithCallSite(_mmPrivateHooks, J9HOOK_MM_PRIVATE_CLASS_UNLOADING_START, verboseHandlerClassUnloadingStart, OMR_GET_CALLSITE(), (void *)this);102(*_mmHooks)->J9HookRegisterWithCallSite(_mmHooks, J9HOOK_MM_CLASS_UNLOADING_END, verboseHandlerClassUnloadingEnd, OMR_GET_CALLSITE(), (void *)this);103#endif /* defined(J9VM_GC_DYNAMIC_CLASS_UNLOADING) */104105(*_mmPrivateHooks)->J9HookRegisterWithCallSite(_mmPrivateHooks, J9HOOK_MM_PRIVATE_OUT_OF_MEMORY, verboseHandlerOutOFMemory, OMR_GET_CALLSITE(), (void *)this);106(*_mmPrivateHooks)->J9HookRegisterWithCallSite(_mmPrivateHooks, J9HOOK_MM_PRIVATE_UTILIZATION_TRACKER_OVERFLOW, verboseHandlerUtilTrackerOverflow, OMR_GET_CALLSITE(), (void *)this);107(*_mmPrivateHooks)->J9HookRegisterWithCallSite(_mmPrivateHooks, J9HOOK_MM_PRIVATE_NON_MONOTONIC_TIME, verboseHandlerNonMonotonicTime, OMR_GET_CALLSITE(), (void *)this);108}109110void111MM_VerboseHandlerOutputRealtime::disableVerbose()112{113MM_VerboseHandlerOutput::disableVerbose();114115/* Cycle */116(*_mmOmrHooks)->J9HookUnregister(_mmOmrHooks, J9HOOK_MM_OMR_GC_CYCLE_START, verboseHandlerCycleStart, NULL);117(*_mmPrivateHooks)->J9HookUnregister(_mmPrivateHooks, J9HOOK_MM_PRIVATE_GC_POST_CYCLE_END, verboseHandlerCycleEnd, NULL);118119/* trigger */120(*_mmPrivateHooks)->J9HookUnregister(_mmPrivateHooks, J9HOOK_MM_PRIVATE_METRONOME_TRIGGER_START, verboseHandlerTriggerStart, NULL);121(*_mmPrivateHooks)->J9HookUnregister(_mmPrivateHooks, J9HOOK_MM_PRIVATE_METRONOME_TRIGGER_END, verboseHandlerTriggerEnd, NULL);122123/* increment */124(*_mmPrivateHooks)->J9HookUnregister(_mmPrivateHooks, J9HOOK_MM_PRIVATE_METRONOME_INCREMENT_START, verboseHandlerIncrementStart, NULL);125(*_mmPrivateHooks)->J9HookUnregister(_mmPrivateHooks, J9HOOK_MM_PRIVATE_METRONOME_INCREMENT_END, verboseHandlerIncrementEnd, NULL);126127/* sync gc */128(*_mmPrivateHooks)->J9HookUnregister(_mmPrivateHooks, J9HOOK_MM_PRIVATE_METRONOME_SYNCHRONOUS_GC_START, verboseHandlerSyncGCStart, NULL);129(*_mmPrivateHooks)->J9HookUnregister(_mmPrivateHooks, J9HOOK_MM_PRIVATE_METRONOME_SYNCHRONOUS_GC_END, verboseHandlerSyncGCEnd, NULL);130131/* mark, class unload, sweep phases */132(*_mmPrivateHooks)->J9HookUnregister(_mmPrivateHooks, J9HOOK_MM_PRIVATE_MARK_START, verboseHandlerMarkStart, NULL);133(*_mmPrivateHooks)->J9HookUnregister(_mmPrivateHooks, J9HOOK_MM_PRIVATE_MARK_END, verboseHandlerMarkEnd, NULL);134(*_mmPrivateHooks)->J9HookUnregister(_mmPrivateHooks, J9HOOK_MM_PRIVATE_SWEEP_START, verboseHandlerSweepStart, NULL);135(*_mmPrivateHooks)->J9HookUnregister(_mmPrivateHooks, J9HOOK_MM_PRIVATE_SWEEP_END, verboseHandlerSweepEnd, NULL);136#if defined(J9VM_GC_DYNAMIC_CLASS_UNLOADING)137(*_mmPrivateHooks)->J9HookUnregister(_mmPrivateHooks, J9HOOK_MM_PRIVATE_CLASS_UNLOADING_START, verboseHandlerClassUnloadingStart, NULL);138(*_mmHooks)->J9HookUnregister(_mmHooks, J9HOOK_MM_CLASS_UNLOADING_END, verboseHandlerClassUnloadingEnd, NULL);139#endif /* defined(J9VM_GC_DYNAMIC_CLASS_UNLOADING) */140141(*_mmPrivateHooks)->J9HookUnregister(_mmPrivateHooks, J9HOOK_MM_PRIVATE_OUT_OF_MEMORY, verboseHandlerOutOFMemory, NULL);142(*_mmPrivateHooks)->J9HookUnregister(_mmPrivateHooks, J9HOOK_MM_PRIVATE_UTILIZATION_TRACKER_OVERFLOW, verboseHandlerUtilTrackerOverflow, NULL);143(*_mmPrivateHooks)->J9HookUnregister(_mmPrivateHooks, J9HOOK_MM_PRIVATE_NON_MONOTONIC_TIME, verboseHandlerNonMonotonicTime, NULL);144}145146bool147MM_VerboseHandlerOutputRealtime::getThreadName(char *buf, UDATA bufLen, OMR_VMThread *vmThread)148{149return MM_VerboseHandlerJava::getThreadName(buf,bufLen,vmThread);150}151152void153MM_VerboseHandlerOutputRealtime::writeVmArgs(MM_EnvironmentBase* env, MM_VerboseBuffer* buffer)154{155MM_VerboseHandlerJava::writeVmArgs(env, buffer, static_cast<J9JavaVM*>(_omrVM->_language_vm));156}157158const char *159MM_VerboseHandlerOutputRealtime::getCycleType(UDATA type)160{161const char* cycleType = NULL;162switch (type) {163case OMR_GC_CYCLE_TYPE_DEFAULT:164cycleType = "default";165break;166case OMR_GC_CYCLE_TYPE_GLOBAL:167cycleType = "global";168break;169default:170cycleType = "unknown";171break;172}173174return cycleType;175}176177void178MM_VerboseHandlerOutputRealtime::outputInitializedInnerStanza(MM_EnvironmentBase *env, MM_VerboseBuffer *buffer){179MM_GCExtensionsBase *extensions = env->getExtensions();180outputInitializedRegion(env, buffer);181buffer->formatAndOutput(env, 1, "<metronome>");182buffer->formatAndOutput(env, 2, "<attribute name=\"beatsPerMeasure\" value=\"%zu\" />", extensions->beatMicro);183buffer->formatAndOutput(env, 2, "<attribute name=\"timeInterval\" value=\"%zu\" />", extensions->timeWindowMicro);184buffer->formatAndOutput(env, 2, "<attribute name=\"targetUtilization\" value=\"%zu\" />", extensions->targetUtilizationPercentage);185buffer->formatAndOutput(env, 2, "<attribute name=\"trigger\" value=\"0x%zx\" />", extensions->gcTrigger);186buffer->formatAndOutput(env, 2, "<attribute name=\"headRoom\" value=\"0x%zx\" />", extensions->headRoom);187buffer->formatAndOutput(env, 1, "</metronome>");188}189190void191MM_VerboseHandlerOutputRealtime::handleEvent(MM_MetronomeIncrementStartEvent* eventData)192{193/* if we are in a sync gc cycle, do nothing here and let the syncgc stanza handle things */194if (!_syncGCTriggered) {195if (0 == _heartbeatStartTime) {196_heartbeatStartTime = eventData->timestamp;197}198_incrementStartTime = eventData->timestamp;199_incrementCount++;200_totalExclusiveAccessTime += eventData->exclusiveAccessTime;201_maxExclusiveAccessTime = OMR_MAX(eventData->exclusiveAccessTime, _maxExclusiveAccessTime);202_minExclusiveAccessTime = OMR_MIN(eventData->exclusiveAccessTime, _minExclusiveAccessTime);203} else {204/* if we are in a sync GC cycle, only collect the exclusive access time */205_syncGCExclusiveAccessTime = eventData->exclusiveAccessTime;206}207}208209void210MM_VerboseHandlerOutputRealtime::writeHeartbeatData(MM_EnvironmentBase* env, U_64 timestamp)211{212/* if we are in a sync gc cycle OR if there is no heartbeat data, nothing to do */213if (!_syncGCTriggered && 0 != _heartbeatStartTime) {214MM_VerboseWriterChain* writer = _manager->getWriterChain();215PORT_ACCESS_FROM_ENVIRONMENT(env);216217char tagTemplate[200];218getTagTemplate(tagTemplate, sizeof(tagTemplate), _manager->getIdAndIncrement(), "heartbeat", env->_cycleState->_verboseContextID, j9time_current_time_millis());219enterAtomicReportingBlock();220writer->formatAndOutput(env, 0, "<gc-op %s>", tagTemplate);221222U_64 maxQuantaTime = j9time_hires_delta(_heartbeatStartTime, _maxIncrementStartTime, J9PORT_TIME_DELTA_IN_MICROSECONDS);223U_64 meanIncrementTime = _totalIncrementTime / _incrementCount;224const char *gcPhase = NULL;225if(incrementStartsInPreviousGCPhase()) {226gcPhase = getGCPhaseAsString(_previousGCPhase);227_previousGCPhase = _gcPhase;228} else {229gcPhase = getGCPhaseAsString(_gcPhase);230}231writer->formatAndOutput(232env, 1 /*indent*/,233"<quanta quantumCount=\"%zu\" quantumType=\"%s\" minTimeMs=\"%llu.%03.3llu\" meanTimeMs=\"%llu.%03.3llu\" maxTimeMs=\"%llu.%03.3llu\" maxTimestampMs=\"%llu.%03.3llu\" />",234_incrementCount,235gcPhase,236_minIncrementTime / 1000,237_minIncrementTime % 1000,238meanIncrementTime / 1000,239meanIncrementTime % 1000,240_maxIncrementTime / 1000,241_maxIncrementTime % 1000,242maxQuantaTime / 1000,243maxQuantaTime % 1000244);245246U_64 meanExclusiveAccessTime = _totalExclusiveAccessTime / _incrementCount;247writer->formatAndOutput(248env, 1 /*indent*/,249"<exclusiveaccess-info minTimeMs=\"%llu.%03.3llu\" meanTimeMs=\"%llu.%03.3llu\" maxTimeMs=\"%llu.%03.3llu\" />",250_minExclusiveAccessTime / 1000,251_minExclusiveAccessTime % 1000,252meanExclusiveAccessTime / 1000,253meanExclusiveAccessTime % 1000,254_maxExclusiveAccessTime / 1000,255_maxExclusiveAccessTime % 1000256);257258if ((0 != _classesUnloadedTotal) || (0 != _classLoadersUnloadedTotal)) {259writer->formatAndOutput(260env, 1 /*indent*/,261"<classunload-info classloadersunloaded=\"%zu\" classesunloaded=\"%zu\" anonymousclassesunloaded=\"%zu\" />",262_classLoadersUnloadedTotal,263_classesUnloadedTotal,264_anonymousClassesUnloadedTotal265);266}267268if (0 != _softReferenceClearCountTotal) {269writer->formatAndOutput(270env, 1, "<references type=\"soft\" cleared=\"%zu\" dynamicThreshold=\"%zu\" maxThreshold=\"%zu\" />",271_weakReferenceClearCountTotal,272_dynamicSoftReferenceThreshold,273_softReferenceThreshold274);275}276if (0 != _weakReferenceClearCountTotal) {277writer->formatAndOutput(env, 1, "<references type=\"weak\" cleared=\"%zu\" />", _weakReferenceClearCountTotal);278}279if (0 != _phantomReferenceClearCountTotal) {280writer->formatAndOutput(env, 1, "<references type=\"phantom\" cleared=\"%zu\" />", _phantomReferenceClearCountTotal);281}282283if (0 != _finalizableCountTotal) {284writer->formatAndOutput(env, 1, "<finalization enqueued=\"%zu\" />", _finalizableCountTotal);285}286287if ((0 != _workPacketOverflowCountTotal) || (0 != _objectOverflowCountTotal)) {288writer->formatAndOutput(289env, 1 /*indent*/,290"<work-packet-overflow packetCount=\"%zu\" directObjectCount=\"%zu\" />",291_workPacketOverflowCountTotal,292_objectOverflowCountTotal293);294}295296if (0 != _nonDeterministicSweepTotal) {297writer->formatAndOutput(298env, 1 /*indent*/,299"<nondeterministic-sweep maxTimeMs=\"%llu.%03.3llu\" totalRegions=\"%zu\" maxRegions=\"%zu\" />",300_nonDeterministicSweepDelayMax / 1000,301_nonDeterministicSweepDelayMax % 1000,302_nonDeterministicSweepTotal,303_nonDeterministicSweepConsecutiveMax304);305}306307U_64 meanHeapFree = _totalHeapFree / _incrementCount;308writer->formatAndOutput(309env, 1 /*indent*/,310"<free-mem type=\"heap\" minBytes=\"%llu\" meanBytes=\"%llu\" maxBytes=\"%llu\" />",311_minHeapFree,312meanHeapFree,313_maxHeapFree314);315316writer->formatAndOutput(317env, 1 /*indent*/,318"<thread-priority maxPriority=\"%zu\" minPriority=\"%zu\" />",319_maxStartPriority,320_minStartPriority321);322323writer->formatAndOutput(env, 0, "</gc-op>");324writer->flush(env);325exitAtomicReportingBlock();326}327}328329void330MM_VerboseHandlerOutputRealtime::writeHeartbeatDataAndResetHeartbeatStats(MM_EnvironmentBase* env, U_64 timestamp)331{332writeHeartbeatData(env, timestamp);333resetHeartbeatStats();334}335336void337MM_VerboseHandlerOutputRealtime::handleEvent(MM_MetronomeIncrementEndEvent* eventData)338{339/* process only if we are in a heartbeat */340if (0 != _heartbeatStartTime) {341MM_EnvironmentBase* env = MM_EnvironmentBase::getEnvironment(eventData->currentThread);342MM_GCExtensions* extensions = MM_GCExtensions::getExtensions(env->getOmrVM());343344PORT_ACCESS_FROM_ENVIRONMENT(env);345346U_64 incrementTime = j9time_hires_delta(_incrementStartTime, eventData->timestamp, J9PORT_TIME_DELTA_IN_MICROSECONDS);347_totalIncrementTime += incrementTime;348if (incrementTime > _maxIncrementTime) {349_maxIncrementTime = incrementTime;350_maxIncrementStartTime = _incrementStartTime;351}352/* reset increment start time */353_incrementStartTime = 0;354_minIncrementTime = OMR_MIN(incrementTime, _minIncrementTime);355356_classLoadersUnloadedTotal += extensions->globalGCStats.metronomeStats.classLoaderUnloadedCount;357_classesUnloadedTotal += extensions->globalGCStats.metronomeStats.classesUnloadedCount;358_anonymousClassesUnloadedTotal += extensions->globalGCStats.metronomeStats.anonymousClassesUnloadedCount;359360_weakReferenceClearCountTotal += extensions->markJavaStats._weakReferenceStats._cleared;361_softReferenceClearCountTotal += extensions->markJavaStats._softReferenceStats._cleared;362_softReferenceThreshold = extensions->getMaxSoftReferenceAge();363_dynamicSoftReferenceThreshold = extensions->getDynamicMaxSoftReferenceAge();364_phantomReferenceClearCountTotal += extensions->markJavaStats._phantomReferenceStats._cleared;365366_finalizableCountTotal += extensions->markJavaStats._unfinalizedEnqueued;367368_workPacketOverflowCountTotal += extensions->globalGCStats.metronomeStats.getWorkPacketOverflowCount();369_objectOverflowCountTotal += extensions->globalGCStats.metronomeStats.getObjectOverflowCount();370371_nonDeterministicSweepTotal += extensions->globalGCStats.metronomeStats.nonDeterministicSweepCount;372_nonDeterministicSweepConsecutiveMax = OMR_MAX(_nonDeterministicSweepConsecutiveMax, extensions->globalGCStats.metronomeStats.nonDeterministicSweepConsecutive);373_nonDeterministicSweepDelayMax = OMR_MAX(_nonDeterministicSweepDelayMax, extensions->globalGCStats.metronomeStats.nonDeterministicSweepDelay);374375_maxHeapFree = OMR_MAX(_maxHeapFree, _extensions->heap->getApproximateActiveFreeMemorySize());376_totalHeapFree += _extensions->heap->getApproximateActiveFreeMemorySize();377_minHeapFree = OMR_MIN(_minHeapFree, _extensions->heap->getApproximateActiveFreeMemorySize());378379UDATA startPriority = omrthread_get_priority(eventData->currentThread->_os_thread);380_maxStartPriority = OMR_MAX(_maxStartPriority, startPriority);381_minStartPriority = OMR_MIN(_minStartPriority, startPriority);382383U_64 timeSinceHeartbeatStart = j9time_hires_delta(_heartbeatStartTime, eventData->timestamp, J9PORT_TIME_DELTA_IN_MICROSECONDS);384if (((timeSinceHeartbeatStart / 1000) >= extensions->verbosegcCycleTime)385|| (incrementStartsInPreviousGCPhase())) {386writeHeartbeatDataAndResetHeartbeatStats(env, eventData->timestamp);387}388}389}390391void392MM_VerboseHandlerOutputRealtime::handleEvent(MM_MetronomeSynchronousGCStartEvent* eventData)393{394/* we hit a sync GC, flush heartbeat data collected so far */395writeHeartbeatDataAndResetHeartbeatStats(MM_EnvironmentBase::getEnvironment(eventData->currentThread), eventData->timestamp);396397_syncGCTriggered = true;398_syncGCStartTime = eventData->timestamp;399_syncGCReason = (GCReason)eventData->reason;400_syncGCReasonParameter = eventData->reasonParameter;401_syncGCStartHeapFree = eventData->heapFree;402_syncGCStartImmortalFree = eventData->immortalFree;403_syncGCStartClassLoadersUnloaded = eventData->classLoadersUnloaded;404_syncGCStartClassesUnloaded = eventData->classesUnloaded;405_syncGCStartAnonymousClassesUnloaded = eventData->anonymousClassesUnloaded;406}407408void409MM_VerboseHandlerOutputRealtime::handleEvent(MM_MetronomeSynchronousGCEndEvent* eventData)410{411MM_EnvironmentBase* env = MM_EnvironmentBase::getEnvironment(eventData->currentThread);412PORT_ACCESS_FROM_ENVIRONMENT(env);413char tagTemplate[200];414MM_VerboseWriterChain* writer = _manager->getWriterChain();415enterAtomicReportingBlock();416417U_64 syncGCTimeDuration = 0;418bool deltaTimeSuccess = getTimeDeltaInMicroSeconds(&syncGCTimeDuration, _syncGCStartTime, eventData->timestamp);419420getTagTemplate(tagTemplate, sizeof(tagTemplate), _manager->getIdAndIncrement(), "syncgc", env->_cycleState->_verboseContextID, syncGCTimeDuration, j9time_current_time_millis());421422if (!deltaTimeSuccess) {423writer->formatAndOutput(env, 0, "<warning details=\"clock error detected, following timing may be inaccurate\" />");424}425426writer->formatAndOutput(env, 0, "<gc-op %s>", tagTemplate);427428const char *hookReason = getGCReasonAsString(_syncGCReason);429if (_syncGCReason == OUT_OF_MEMORY_TRIGGER) {430writer->formatAndOutput(431env, 1 /*indent*/,432"<syncgc-info reason=\"%s\" totalBytesRequested=\"%zu\" exclusiveaccessTimeMs=\"%llu.%03.3llu\" threadPriority=\"%zu\" />",433hookReason,434_syncGCReasonParameter,435_syncGCExclusiveAccessTime / 1000,436_syncGCExclusiveAccessTime % 1000,437omrthread_get_priority(eventData->currentThread->_os_thread)438);439} else {440writer->formatAndOutput(441env, 1 /*indent*/,442"<syncgc-info reason=\"%s\" exclusiveaccessTimeMs=\"%llu.%03.3llu\" threadPriority=\"%zu\" />",443hookReason,444_syncGCExclusiveAccessTime / 1000,445_syncGCExclusiveAccessTime % 1000,446omrthread_get_priority(eventData->currentThread->_os_thread)447);448}449450writer->formatAndOutput(env, 1, "<free-mem-delta type=\"heap\" bytesBefore=\"%zu\" bytesAfter=\"%zu\" />", _syncGCStartHeapFree, eventData->heapFree);451452if ((0 != eventData->workPacketOverflowCount) || (0 != eventData->objectOverflowCount)) {453writer->formatAndOutput(454env, 1 /*indent*/,455"<work-packet-overflow packetCount=\"%zu\" directObjectCount=\"%zu\" />",456eventData->workPacketOverflowCount,457eventData->objectOverflowCount458);459}460461if ((_syncGCStartClassesUnloaded != eventData->classesUnloaded) || (_syncGCStartClassLoadersUnloaded != eventData->classLoadersUnloaded)) {462writer->formatAndOutput(463env, 1 /*indent*/,464"<classunload-info classloadersunloaded=\"%zu\" classesunloaded=\"%zu\" anonymousclassesunloaded=\"%zu\" />",465eventData->classLoadersUnloaded - _syncGCStartClassLoadersUnloaded,466eventData->classesUnloaded - _syncGCStartClassesUnloaded,467eventData->anonymousClassesUnloaded - _syncGCStartAnonymousClassesUnloaded468);469}470471if (0 != eventData->softReferenceClearCount) {472writer->formatAndOutput(473env, 1,474"<references type=\"soft\" cleared=\"%zu\" dynamicThreshold=\"%zu\" maxThreshold=\"%zu\" />",475eventData->softReferenceClearCount,476eventData->dynamicSoftReferenceThreshold,477eventData->softReferenceThreshold478);479}480if (0 != eventData->weakReferenceClearCount) {481writer->formatAndOutput(env, 1, "<references type=\"weak\" cleared=\"%zu\" />",eventData->weakReferenceClearCount);482}483if (0 != eventData->phantomReferenceClearCount) {484writer->formatAndOutput(env, 1, "<references type=\"phantom\" cleared=\"%zu\" />",eventData->phantomReferenceClearCount);485}486487if (0 != eventData->finalizableCount) {488writer->formatAndOutput(env, 1,"<finalization enqueued=\"%zu\" />", eventData->finalizableCount);489}490491writer->formatAndOutput(env, 0, "</gc-op>");492writer->flush(env);493exitAtomicReportingBlock();494495resetSyncGCStats();496}497498void499MM_VerboseHandlerOutputRealtime::handleCycleStart(J9HookInterface** hook, UDATA eventNum, void* eventData)500{501MM_VerboseHandlerOutput::handleCycleStart(hook, eventNum, eventData);502/* set the gc phase to mark at the start of the cycle */503_previousGCPhase = _gcPhase = PRE_COLLECT;504}505506void507MM_VerboseHandlerOutputRealtime::handleCycleEnd(J9HookInterface** hook, UDATA eventNum, void* eventData)508{509MM_GCPostCycleEndEvent* cycleEndEvent = (MM_GCPostCycleEndEvent*)eventData;510writeHeartbeatDataAndResetHeartbeatStats(MM_EnvironmentBase::getEnvironment(cycleEndEvent->currentThread), cycleEndEvent->timestamp);511MM_VerboseHandlerOutput::handleCycleEnd(hook, eventNum, eventData);512/* set the gc phase to inactive at the end of the cycle */513_previousGCPhase = _gcPhase = INACTIVE;514}515516void517MM_VerboseHandlerOutputRealtime::handleEvent(MM_MarkStartEvent* eventData)518{519_previousGCPhase = _gcPhase = MARK;520}521522void523MM_VerboseHandlerOutputRealtime::handleEvent(MM_MarkEndEvent* eventData)524{525_previousGCPhase = MARK;526}527528void529MM_VerboseHandlerOutputRealtime::handleEvent(MM_ClassUnloadingStartEvent* eventData)530{531_gcPhase = CLASS_UNLOAD;532}533534void535MM_VerboseHandlerOutputRealtime::handleEvent(MM_ClassUnloadingEndEvent* eventData)536{537if (!incrementStartsInPreviousGCPhase()) {538_previousGCPhase = CLASS_UNLOAD;539}540}541542void543MM_VerboseHandlerOutputRealtime::handleEvent(MM_SweepStartEvent* eventData)544{545_gcPhase = SWEEP;546}547548void549MM_VerboseHandlerOutputRealtime::handleEvent(MM_SweepEndEvent* eventData)550{551if (!incrementStartsInPreviousGCPhase()) {552_previousGCPhase = SWEEP;553}554_gcPhase = POST_COLLECT;555}556557void558MM_VerboseHandlerOutputRealtime::handleEvent(MM_OutOfMemoryEvent* eventData)559{560MM_EnvironmentBase* env = MM_EnvironmentBase::getEnvironment(eventData->currentThread);561MM_VerboseWriterChain* writer = _manager->getWriterChain();562PORT_ACCESS_FROM_ENVIRONMENT(env);563char tagTemplate[200];564getTagTemplate(tagTemplate, sizeof(tagTemplate), _manager->getIdAndIncrement(), j9time_current_time_millis());565566enterAtomicReportingBlock();567writer->formatAndOutput(568env, 0 /*indent*/,569"<out-of-memory %s memorySpaceName=\"%s\" memorySpaceAddress=\"%p\" />",570tagTemplate,571eventData->memorySpaceString,572eventData->memorySpace573);574writer->flush(env);575exitAtomicReportingBlock();576}577578void579MM_VerboseHandlerOutputRealtime::handleEvent(MM_UtilizationTrackerOverflowEvent* eventData)580{581MM_EnvironmentBase* env = MM_EnvironmentBase::getEnvironment(eventData->currentThread);582writeHeartbeatDataAndResetHeartbeatStats(env, eventData->timestamp);583MM_VerboseWriterChain* writer = _manager->getWriterChain();584PORT_ACCESS_FROM_ENVIRONMENT(env);585char tagTemplate[200];586getTagTemplate(tagTemplate, sizeof(tagTemplate), _manager->getIdAndIncrement(), j9time_current_time_millis());587588enterAtomicReportingBlock();589writer->formatAndOutput(590env, 0 /*indent*/,591"<utilization-tracker-overflow %s utilizationTrackerAddress=\"%p\" timeSliceDurationArrayAddress=\"%p\" timeSliceCursor=\"%zu\" />",592tagTemplate,593eventData->utilizationTrackerAddress,594eventData->timeSliceDurationArrayAddress,595eventData->timeSliceCursor596);597writer->flush(env);598exitAtomicReportingBlock();599}600601void602MM_VerboseHandlerOutputRealtime::handleEvent(MM_NonMonotonicTimeEvent* eventData)603{604MM_EnvironmentBase* env = MM_EnvironmentBase::getEnvironment(eventData->currentThread);605writeHeartbeatDataAndResetHeartbeatStats(env, eventData->timestamp);606MM_VerboseWriterChain* writer = _manager->getWriterChain();607PORT_ACCESS_FROM_ENVIRONMENT(env);608char tagTemplate[200];609getTagTemplate(tagTemplate, sizeof(tagTemplate), _manager->getIdAndIncrement(), j9time_current_time_millis());610611enterAtomicReportingBlock();612writer->formatAndOutput(env, 0, "<non-monotonic-time timerDescription=\"%s\" %s />", eventData->timerDesc, tagTemplate);613writer->flush(env);614exitAtomicReportingBlock();615}616617618