Skip to content

Commit 19c14ce

Browse files
authored
Merge pull request #23652 from adpopescu/jfr-gc-heap-summary
Add JFR GC Heap Summary event
2 parents 36a9296 + 96405bb commit 19c14ce

14 files changed

Lines changed: 179 additions & 12 deletions

File tree

runtime/gc/gctable.c

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -225,6 +225,8 @@ J9MemoryManagerFunctions MemoryManagerFunctions = {
225225
j9gc_get_sum_of_pauses,
226226
j9gc_register_jfr_hooks,
227227
j9gc_deregister_jfr_hooks,
228+
j9gc_get_heap_base,
229+
j9gc_get_heap_top,
228230
j9gc_modron_global_collect,
229231
j9gc_modron_global_collect_with_overrides,
230232
j9gc_modron_local_collect,

runtime/gc_base/GCJFR.cpp

Lines changed: 39 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -30,12 +30,16 @@
3030
#include "mmomrhook.h"
3131
#include "modronapi.hpp"
3232

33+
#define BEFORE_GC 0
34+
#define AFTER_GC 1
35+
3336
/**
3437
* Register GC-related JFR hooks.
3538
*
3639
* This function registers all garbage collection related hooks for JFR event recording:
37-
* - jfrPublioGCEndHook (corresponding to public OMR hook)
38-
* - jfrPrivateGCEndHook (corresponding to private OMR hook)
40+
* - jfrGCCycleStartHook (corresponding to public OMR GC cycle start trigger)
41+
* - jfrPublicGCEndHook (corresponding to public OMR GC cycle end trigger)
42+
* - jfrPrivateGCEndHook (corresponding to private OMR GC cycle end trigger)
3943
*
4044
* @param vm[in] The Java VM
4145
* @return 0 on success, non-zero on failure
@@ -46,6 +50,9 @@ jfrRegisterGCHooks(J9JavaVM *vm)
4650
J9HookInterface** gcOmrHooks = vm->memoryManagerFunctions->j9gc_get_omr_hook_interface(vm->omrVM);
4751
J9HookInterface** gcPrivateHooks = vm->memoryManagerFunctions->j9gc_get_private_hook_interface(vm);
4852

53+
if ((*gcOmrHooks)->J9HookRegisterWithCallSite(gcOmrHooks, J9HOOK_MM_OMR_GC_CYCLE_START, jfrGCCycleStartHook, OMR_GET_CALLSITE(), NULL)) {
54+
return -1;
55+
}
4956
if ((*gcOmrHooks)->J9HookRegisterWithCallSite(gcOmrHooks, J9HOOK_MM_OMR_GC_CYCLE_END, jfrPublicGCEndHook, OMR_GET_CALLSITE(), NULL)) {
5057
return -1;
5158
}
@@ -62,9 +69,32 @@ jfrRegisterGCHooks(J9JavaVM *vm)
6269
}
6370

6471
/**
65-
* JFR GC Hook corresponding to public OMR hook data.
72+
* JFR GC Hook corresponding to public OMR cycle start trigger.
73+
*
74+
* This function emits all garbage collection related JFR events on the public OMR cycle start trigger.
75+
*
76+
* @param hook[in] the VM hook interface
77+
* @param eventNum[in] the event number
78+
* @param eventData[in] the event data
79+
* @param userData[in] the registered user data
80+
*/
81+
void
82+
jfrGCCycleStartHook(J9HookInterface **hook, UDATA eventNum, void *eventData, void *userData)
83+
{
84+
MM_GCCycleStartEvent *event = (MM_GCCycleStartEvent *)eventData;
85+
OMR_VMThread *omrVMThread = (OMR_VMThread *)event->omrVMThread;
86+
J9VMThread *currentThread = (J9VMThread *)omrVMThread->_language_vmthread;
87+
J9JavaVM *javaVM = currentThread->javaVM;
88+
J9InternalVMFunctions *vmFuncs = javaVM->internalVMFunctions;
89+
90+
/* Emit heap summary with gcWhenID = BeforeGC */
91+
vmFuncs->jfrGCHeapSummary(omrVMThread, BEFORE_GC);
92+
}
93+
94+
/**
95+
* JFR GC Hook corresponding to public OMR cycle end trigger.
6696
*
67-
* This function calls all garbage collection related JFR event recording functions on the public OMR hook.
97+
* This function emits all garbage collection related JFR events on the public OMR cycle end trigger.
6898
*
6999
* @param hook[in] the VM hook interface
70100
* @param eventNum[in] the event number
@@ -88,9 +118,9 @@ jfrPublicGCEndHook(J9HookInterface **hook, UDATA eventNum, void *eventData, void
88118
}
89119

90120
/**
91-
* JFR GC Hook corresponding to private OMR hook data.
121+
* JFR GC Hook corresponding to private OMR cycle end trigger.
92122
*
93-
* This function calls all garbage collection related JFR event recording functions on the public OMR hook.
123+
* This function emits all garbage collection related JFR events on the private OMR cycle end trigger.
94124
*
95125
* @param hook[in] the VM hook interface
96126
* @param eventNum[in] the event number
@@ -107,6 +137,8 @@ jfrPrivateGCEndHook(J9HookInterface **hook, UDATA eventNum, void *eventData, voi
107137
J9InternalVMFunctions *vmFuncs = javaVM->internalVMFunctions;
108138

109139
vmFuncs->jfrGarbageCollection(omrVMThread);
140+
/* Emit heap summary with gcWhenID = AfterGC */
141+
vmFuncs->jfrGCHeapSummary(omrVMThread, AFTER_GC);
110142

111143
}
112144

@@ -124,6 +156,7 @@ jfrDeregisterGCHooks(J9JavaVM *vm)
124156
J9HookInterface** gcOmrHooks = vm->memoryManagerFunctions->j9gc_get_omr_hook_interface(vm->omrVM);
125157
J9HookInterface** gcPrivateHooks = vm->memoryManagerFunctions->j9gc_get_private_hook_interface(vm);
126158

159+
(*gcOmrHooks)->J9HookUnregister(gcOmrHooks, J9HOOK_MM_OMR_GC_CYCLE_START, jfrGCCycleStartHook, NULL);
127160
(*gcOmrHooks)->J9HookUnregister(gcOmrHooks, J9HOOK_MM_OMR_GC_CYCLE_END, jfrPublicGCEndHook, NULL);
128161
(*gcPrivateHooks)->J9HookUnregister(gcPrivateHooks, J9HOOK_MM_PRIVATE_GC_POST_CYCLE_END, jfrPrivateGCEndHook, NULL);
129162
}

runtime/gc_base/GCJFR.hpp

Lines changed: 13 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -45,6 +45,19 @@ extern "C" {
4545
jint
4646
jfrRegisterGCHooks(J9JavaVM *vm);
4747

48+
/**
49+
* JFR GC Hook for cycle start.
50+
*
51+
* This function emits the GC heap summary event before GC starts.
52+
*
53+
* @param hook[in] the VM hook interface
54+
* @param eventNum[in] the event number
55+
* @param eventData[in] the event data
56+
* @param userData[in] the registered user data
57+
*/
58+
void
59+
jfrGCCycleStartHook(J9HookInterface **hook, UDATA eventNum, void *eventData, void *userData);
60+
4861
/**
4962
* JFR GC Hook corresponding to public OMR hook data.
5063
*

runtime/gc_base/gc_internal.h

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -139,6 +139,8 @@ extern J9_CFUNC jint JNICALL queryGCStatus(JavaVM *vm, jint *nHeaps, GCStatus *
139139
extern J9_CFUNC int j9gc_finalizer_startup(J9JavaVM * vm);
140140
extern J9_CFUNC UDATA j9gc_wait_for_reference_processing(J9JavaVM *vm);
141141
extern J9_CFUNC UDATA j9gc_get_maximum_heap_size(J9JavaVM *javaVM);
142+
extern J9_CFUNC void* j9gc_get_heap_base(J9JavaVM *javaVM);
143+
extern J9_CFUNC void* j9gc_get_heap_top(J9JavaVM *javaVM);
142144
extern J9_CFUNC UDATA j9gc_get_minimum_young_generation_size(J9JavaVM *javaVM);
143145
extern J9_CFUNC UDATA j9gc_get_maximum_young_generation_size(J9JavaVM *javaVM);
144146
extern J9_CFUNC I_32 j9gc_get_jit_string_dedup_policy(J9JavaVM *javaVM);

runtime/gc_base/modronapi.cpp

Lines changed: 20 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -856,6 +856,26 @@ j9gc_get_maximum_heap_size(J9JavaVM *javaVM)
856856
return size;
857857
}
858858

859+
/**
860+
* API to return the heap base address
861+
*/
862+
void *
863+
j9gc_get_heap_base(J9JavaVM *javaVM)
864+
{
865+
MM_GCExtensions *extensions = MM_GCExtensions::getExtensions(javaVM);
866+
return extensions->heap->getHeapBase();
867+
}
868+
869+
/**
870+
* API to return the heap top address
871+
*/
872+
void *
873+
j9gc_get_heap_top(J9JavaVM *javaVM)
874+
{
875+
MM_GCExtensions *extensions = MM_GCExtensions::getExtensions(javaVM);
876+
return extensions->heap->getHeapTop();
877+
}
878+
859879
/**
860880
* API to return the minimum young generation memory size
861881
* for all GC policies that apply:

runtime/gc_base/modronapi.hpp

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -85,6 +85,8 @@ UDATA j9gc_set_softmx(J9JavaVM *javaVM, UDATA newsoftMx);
8585
UDATA j9gc_get_softmx(J9JavaVM *javaVM);
8686
UDATA j9gc_get_initial_heap_size(J9JavaVM *javaVM);
8787
UDATA j9gc_get_maximum_heap_size(J9JavaVM *javaVM);
88+
void *j9gc_get_heap_base(J9JavaVM *javaVM);
89+
void *j9gc_get_heap_top(J9JavaVM *javaVM);
8890
UDATA j9gc_get_minimum_young_generation_size(J9JavaVM *javaVM);
8991
UDATA j9gc_get_maximum_young_generation_size(J9JavaVM *javaVM);
9092
const char *j9gc_get_gcmodestring(J9JavaVM *javaVM);

runtime/oti/j9nonbuilder.h

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -5111,6 +5111,8 @@ typedef struct J9MemoryManagerFunctions {
51115111
U_64 ( *j9gc_get_sum_of_pauses)(struct J9VMThread *vmThread) ;
51125112
jint ( *j9gc_register_jfr_hooks)(struct J9JavaVM *javaVM) ;
51135113
void ( *j9gc_deregister_jfr_hooks)(struct J9JavaVM *javaVM) ;
5114+
void* ( *j9gc_get_heap_base)(struct J9JavaVM *javaVM) ;
5115+
void* ( *j9gc_get_heap_top)(struct J9JavaVM *javaVM) ;
51145116
UDATA ( *j9gc_modron_global_collect)(struct J9VMThread *vmThread) ;
51155117
UDATA ( *j9gc_modron_global_collect_with_overrides)(struct J9VMThread *vmThread, U_32 overrideFlags) ;
51165118
UDATA ( *j9gc_modron_local_collect)(struct J9VMThread *vmThread) ;
@@ -5623,6 +5625,7 @@ typedef struct J9InternalVMFunctions {
56235625
void (*jfrOldGarbageCollection)(struct OMR_VMThread *omrVMThread) ;
56245626
void (*jfrYoungGarbageCollection)(struct OMR_VMThread *omrVMThread) ;
56255627
void (*jfrGarbageCollection)(struct OMR_VMThread *omrVMThread) ;
5628+
void (*jfrGCHeapSummary)(struct OMR_VMThread *omrVMThread, U_32 gcWhenID) ;
56265629
jboolean (*setJFRRecordingFileName)(struct J9JavaVM *vm, char *fileName);
56275630
void (*tearDownJFR)(struct J9JavaVM *vm);
56285631
jlong (*getTypeIdUTF8)(struct J9VMThread *currentThread, struct J9ClassLoader *classLoader, struct J9UTF8 *className, BOOLEAN freeName);

runtime/oti/vm_api.h

Lines changed: 9 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -5846,6 +5846,15 @@ jfrYoungGarbageCollection(OMR_VMThread *omrVMThread);
58465846
void
58475847
jfrGarbageCollection(OMR_VMThread *omrVMThread);
58485848

5849+
/**
5850+
* JFR GC heap summary event.
5851+
*
5852+
* @param omrVMThread[in] the OMR VM thread
5853+
* @param gcWhenID[in] BeforeGC or AfterGC
5854+
*/
5855+
void
5856+
jfrGCHeapSummary(OMR_VMThread *omrVMThread, U_32 gcWhenID);
5857+
58495858
/**
58505859
* Set JFR recording file name.
58515860
*

runtime/vm/JFRChunkWriter.cpp

Lines changed: 25 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -884,6 +884,29 @@ VM_JFRChunkWriter::writeGCCauseTypesEvent()
884884
writeEventSize(dataStart);
885885
}
886886

887+
void
888+
VM_JFRChunkWriter::writeGCWhenTypesEvent()
889+
{
890+
U_8 *dataStart = writeCheckpointEventHeader(Generic, 1);
891+
892+
/* class ID */
893+
_bufferWriter->writeLEB128(GCWhensID);
894+
895+
/* number of states */
896+
_bufferWriter->writeLEB128(GCWhenTypeCount);
897+
898+
for (int i = 0; i < GCWhenTypeCount; i++) {
899+
/* constant index */
900+
_bufferWriter->writeLEB128(i);
901+
902+
/* write string */
903+
writeStringLiteral(gcWhens[i]);
904+
}
905+
906+
/* write size */
907+
writeEventSize(dataStart);
908+
}
909+
887910
void
888911
VM_JFRChunkWriter::writeGCHeapConfigurationEvent()
889912
{
@@ -1592,8 +1615,7 @@ void
15921615
VM_JFRChunkWriter::writeGCHeapSummaryEvent(void *anElement, void *userData)
15931616
{
15941617
GCHeapSummaryEntry *entry = (GCHeapSummaryEntry *)anElement;
1595-
VM_JFRChunkWriter *writer = (VM_JFRChunkWriter *)userData;
1596-
VM_BufferWriter *bufferWriter = writer->_bufferWriter;
1618+
VM_BufferWriter *bufferWriter = (VM_BufferWriter *)userData;
15971619

15981620
/* Reserve size field */
15991621
U_8 *dataStart = reserveEventSize(bufferWriter);
@@ -1608,7 +1630,7 @@ VM_JFRChunkWriter::writeGCHeapSummaryEvent(void *anElement, void *userData)
16081630
bufferWriter->writeLEB128(entry->gcID);
16091631

16101632
/* Write when summary is generated */
1611-
writer->writeStringLiteral(gcWhens[entry->gcWhenID]);
1633+
bufferWriter->writeLEB128(entry->gcWhenID);
16121634

16131635
/* Write heap space info */
16141636
bufferWriter->writeLEB128(entry->heapSpace.start);

runtime/vm/JFRChunkWriter.hpp

Lines changed: 9 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -75,8 +75,8 @@ static constexpr const char * const gcCauses[] = {
7575
};
7676

7777
static constexpr const char * const gcWhens[] = {
78-
"before gc",
79-
"after gc"
78+
"Before GC",
79+
"After GC"
8080
};
8181

8282
enum StringEnconding {
@@ -131,6 +131,7 @@ enum MetadataTypeID {
131131
ThreadStateID = 170,
132132
GCNamesID = 171,
133133
GCCausesID = 172,
134+
GCWhensID = 173,
134135
NarrowOopModesID = 180,
135136
ModuleID = 186,
136137
PackageID = 187,
@@ -194,6 +195,7 @@ class VM_JFRChunkWriter {
194195
static constexpr int OOP_MODES_ENTRY_SIZE = CHECKPOINT_EVENT_HEADER_AND_FOOTER + sizeof(oopModeTypeNames) + (OOPModeTypeCount * STRING_HEADER_LENGTH);
195196
static constexpr int GC_NAMES_ENTRY_SIZE = CHECKPOINT_EVENT_HEADER_AND_FOOTER + sizeof(gcNames) + (GCNameTypeCount * STRING_HEADER_LENGTH);
196197
static constexpr int GC_CAUSES_ENTRY_SIZE = CHECKPOINT_EVENT_HEADER_AND_FOOTER + sizeof(gcCauses) + (GCCauseTypeCount * STRING_HEADER_LENGTH);
198+
static constexpr int GC_WHENS_ENTRY_SIZE = CHECKPOINT_EVENT_HEADER_AND_FOOTER + sizeof(gcWhens) + (GCWhenTypeCount * STRING_HEADER_LENGTH);
197199
static constexpr int CLASS_ENTRY_ENTRY_SIZE = (5 * sizeof(U_64)) + sizeof(U_8);
198200
static constexpr int CLASSLOADER_ENTRY_SIZE = 3 * sizeof(U_64);
199201
static constexpr int PACKAGE_ENTRY_SIZE = (3 * sizeof(U_64)) + sizeof(U_8);
@@ -233,7 +235,7 @@ class VM_JFRChunkWriter {
233235
static constexpr int OLD_GARBAGE_COLLECTION_EVENT_SIZE = sizeof(U_8) + (2 * LEB128_64_SIZE) + (2 * LEB128_32_SIZE);
234236
static constexpr int YOUNG_GARBAGE_COLLECTION_EVENT_SIZE = sizeof(U_8) + (2 * LEB128_64_SIZE) + (3 * LEB128_32_SIZE);
235237
static constexpr int GARBAGE_COLLECTION_EVENT_SIZE = sizeof(U_8) + (6 * LEB128_64_SIZE) + (2 * LEB128_32_SIZE);
236-
static constexpr int GC_HEAP_SUMMARY_EVENT_SIZE = sizeof(U_8) + (7 * LEB128_64_SIZE) + (2 * LEB128_32_SIZE) + STRING_BUFFER_LENGTH;
238+
static constexpr int GC_HEAP_SUMMARY_EVENT_SIZE = sizeof(U_8) + (7 * LEB128_64_SIZE) + (3 * LEB128_32_SIZE);
237239

238240
static constexpr int METADATA_ID = 1;
239241

@@ -408,6 +410,8 @@ class VM_JFRChunkWriter {
408410

409411
writeGCCauseTypesEvent();
410412

413+
writeGCWhenTypesEvent();
414+
411415
writeThreadCheckpointEvent();
412416

413417
writeThreadGroupCheckpointEvent();
@@ -892,6 +896,8 @@ class VM_JFRChunkWriter {
892896

893897
void writeGCCauseTypesEvent();
894898

899+
void writeGCWhenTypesEvent();
900+
895901
void writeGCHeapConfigurationEvent();
896902

897903
void writeYoungGenerationConfigurationEvent();

0 commit comments

Comments
 (0)