Skip to content

Commit 7d59d0f

Browse files
authored
Merge pull request #23155 from thallium/jfr
Add JFR ThreadAllocationStatistics event support
2 parents ce34cc1 + d0f7ad4 commit 7d59d0f

11 files changed

Lines changed: 194 additions & 6 deletions

File tree

runtime/oti/j9consts.h

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1011,6 +1011,7 @@ extern "C" {
10111011
#define J9JFR_EVENT_TYPE_CLASS_LOADER_STATISTICS 31
10121012
#define J9JFR_EVENT_TYPE_NATIVE_LIBRARY 32
10131013
#define J9JFR_EVENT_TYPE_THREAD_DUMP 33
1014+
#define J9JFR_EVENT_TYPE_THREAD_ALLOCATION_STATISTICS 34
10141015

10151016
/* JFR thread states. */
10161017

runtime/oti/j9nonbuilder.h

Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -585,6 +585,11 @@ typedef struct J9JFRThreadDump {
585585
UDATA bufferSize;
586586
} J9JFRThreadDump;
587587

588+
typedef struct J9JFRThreadAllocationStatistics {
589+
J9JFR_EVENT_COMMON_FIELDS
590+
U_64 allocated;
591+
} J9JFRThreadAllocationStatistics;
592+
588593
#endif /* defined(J9VM_OPT_JFR) */
589594

590595
/* @ddr_namespace: map_to_type=J9CfrError */
@@ -6764,6 +6769,9 @@ typedef struct J9JavaVM {
67646769
IDATA jfrAsyncKey;
67656770
IDATA jfrThreadCPULoadAsyncKey;
67666771
UDATA isJFRExcludedOffset;
6772+
#if JAVA_SPEC_VERSION >= 17
6773+
IDATA jfrThreadAllocationStatisticsAsyncKey;
6774+
#endif /* JAVA_SPEC_VERSION >= 17 */
67676775
#endif /* defined(J9VM_OPT_JFR) */
67686776
UDATA unsafeIndexableHeaderSize;
67696777
#if defined(J9VM_OPT_SNAPSHOTS)

runtime/oti/vm_api.h

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -6031,6 +6031,9 @@ requestJFREvent(J9VMThread *currentThread, jlong id);
60316031
UDATA
60326032
getThreadDump(J9VMThread *currentThread, U_8 *buffer, UDATA bufferSize);
60336033

6034+
I_64
6035+
getThreadTID(J9VMThread *currentThread, J9VMThread *vmThread);
6036+
60346037
#endif /* defined(J9VM_OPT_JFR) */
60356038

60366039
#ifdef __cplusplus

runtime/vm/JFRChunkWriter.cpp

Lines changed: 25 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1157,6 +1157,31 @@ VM_JFRChunkWriter::writeClassLoaderStatisticsEvent(void *anElement, void *userDa
11571157
writeEventSize(_bufferWriter, dataStart);
11581158
}
11591159

1160+
void
1161+
VM_JFRChunkWriter::writeThreadAllocationStatisticsEvent(void *anElement, void *userData)
1162+
{
1163+
ThreadAllocationStatisticsEntry *entry = (ThreadAllocationStatisticsEntry *)anElement;
1164+
VM_BufferWriter *_bufferWriter = (VM_BufferWriter *)userData;
1165+
1166+
/* reserve size field */
1167+
U_8 *dataStart = reserveEventSize(_bufferWriter);
1168+
1169+
/* write event type */
1170+
_bufferWriter->writeLEB128(ThreadAllocationStatisticsID);
1171+
1172+
/* write start time */
1173+
_bufferWriter->writeLEB128(entry->ticks);
1174+
1175+
/* write allocated bytes */
1176+
_bufferWriter->writeLEB128(entry->allocated);
1177+
1178+
/* write thread */
1179+
_bufferWriter->writeLEB128(entry->threadIndex);
1180+
1181+
/* write size */
1182+
writeEventSize(_bufferWriter, dataStart);
1183+
}
1184+
11601185
void
11611186
VM_JFRChunkWriter::writeThreadContextSwitchRateEvent(void *anElement, void *userData)
11621187
{

runtime/vm/JFRChunkWriter.hpp

Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -115,6 +115,7 @@ enum MetadataTypeID {
115115
DataLossID = 86,
116116
ClassLoadingStatisticsID = 100,
117117
ClassLoaderStatisticsID = 101,
118+
ThreadAllocationStatisticsID = 107,
118119
PhysicalMemoryID = 108,
119120
ExecutionSampleID = 109,
120121
ThreadDumpID = 111,
@@ -240,6 +241,7 @@ class VM_JFRChunkWriter {
240241
static constexpr int GC_HEAP_SUMMARY_EVENT_SIZE = sizeof(U_8) + (7 * LEB128_64_SIZE) + (3 * LEB128_32_SIZE);
241242
static constexpr int NETWORK_UTILIZATION_EVENT_SIZE = (4 * sizeof(U_64)) + sizeof(U_32);
242243
static constexpr int DATA_LOSS_EVENT_SIZE = sizeof(U_8) + LEB128_32_SIZE + (3 * LEB128_64_SIZE);
244+
static constexpr int THREAD_ALLOCATION_STATISTICS_EVENT_SIZE = sizeof(U_8) + LEB128_32_SIZE + (3 * LEB128_64_SIZE);
243245

244246
static constexpr int METADATA_ID = 1;
245247

@@ -459,6 +461,8 @@ class VM_JFRChunkWriter {
459461

460462
pool_do(_constantPoolTypes.getClassLoaderStatisticsTable(), &writeClassLoaderStatisticsEvent, _bufferWriter);
461463

464+
pool_do(_constantPoolTypes.getThreadAllocationStatisticsTable(), &writeThreadAllocationStatisticsEvent, _bufferWriter);
465+
462466
pool_do(_constantPoolTypes.getThreadContextSwitchRateTable(), &writeThreadContextSwitchRateEvent, _bufferWriter);
463467

464468
pool_do(_constantPoolTypes.getThreadStatisticsTable(), &writeThreadStatisticsEvent, _bufferWriter);
@@ -957,6 +961,8 @@ class VM_JFRChunkWriter {
957961

958962
static void writeClassLoaderStatisticsEvent(void *anElement, void *userData);
959963

964+
static void writeThreadAllocationStatisticsEvent(void *anElement, void *userData);
965+
960966
static void writeThreadContextSwitchRateEvent(void *anElement, void *userData);
961967

962968
static void writeThreadStatisticsEvent(void *anElement, void *userData);
@@ -1059,6 +1065,8 @@ class VM_JFRChunkWriter {
10591065

10601066
requiredBufferSize += _constantPoolTypes.getClassLoaderStatisticsCount() * CLASS_LOADER_STATISTICS_EVENT_SIZE;
10611067

1068+
requiredBufferSize += _constantPoolTypes.getThreadAllocationStatisticsCount() * THREAD_ALLOCATION_STATISTICS_EVENT_SIZE;
1069+
10621070
requiredBufferSize += _constantPoolTypes.getThreadContextSwitchRateCount() * THREAD_CONTEXT_SWITCH_RATE_SIZE;
10631071

10641072
requiredBufferSize += _constantPoolTypes.getThreadStatisticsCount() * THREAD_STATISTICS_EVENT_SIZE;

runtime/vm/JFRConstantPoolTypes.cpp

Lines changed: 18 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1547,6 +1547,24 @@ VM_JFRConstantPoolTypes::addThreadDumpEntry(J9JFRThreadDump *threadDumpData)
15471547
return;
15481548
}
15491549

1550+
void
1551+
VM_JFRConstantPoolTypes::addThreadAllocationStatistics(J9JFRThreadAllocationStatistics *threadAlocationData)
1552+
{
1553+
ThreadAllocationStatisticsEntry *entry = (ThreadAllocationStatisticsEntry *)pool_newElement(_threadAllocationStatisticsTable);
1554+
1555+
if (NULL == entry) {
1556+
_buildResult = OutOfMemory;
1557+
goto done;
1558+
}
1559+
1560+
entry->ticks = threadAlocationData->startTicks;
1561+
entry->threadIndex = threadAlocationData->currentThreadTID;
1562+
entry->allocated = threadAlocationData->allocated;
1563+
1564+
done:
1565+
return;
1566+
}
1567+
15501568
void
15511569
VM_JFRConstantPoolTypes::printTables()
15521570
{

runtime/vm/JFRConstantPoolTypes.hpp

Lines changed: 73 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -315,6 +315,12 @@ struct ClassLoaderStatisticsEntry {
315315
U_64 hiddenBlockSize;
316316
};
317317

318+
struct ThreadAllocationStatisticsEntry {
319+
I_64 ticks;
320+
U_64 threadIndex;
321+
U_64 allocated;
322+
};
323+
318324
struct ThreadContextSwitchRateEntry {
319325
I_64 ticks;
320326
float switchRate;
@@ -555,6 +561,8 @@ class VM_JFRConstantPoolTypes {
555561
UDATA _dataLossCount;
556562
J9Pool *_threadDumpTable;
557563
UDATA _threadDumpCount;
564+
J9Pool *_threadAllocationStatisticsTable;
565+
UDATA _threadAllocationStatisticsCount;
558566

559567
/* Periodic events. */
560568
bool _shouldWriteJVMInformation;
@@ -727,8 +735,6 @@ class VM_JFRConstantPoolTypes {
727735

728736
U_32 addStringUTF8Entry(J9UTF8 *string, bool free);
729737

730-
U_32 addThreadEntry(J9VMThread *vmThread);
731-
732738
U_32 addNetworkInterfaceNameEntry(const char *networkInterfaceName);
733739

734740
U_32 addThreadGroupEntry(j9object_t threadGroup);
@@ -879,6 +885,8 @@ class VM_JFRConstantPoolTypes {
879885

880886
void addThreadDumpEntry(J9JFRThreadDump *threadDumpData);
881887

888+
void addThreadAllocationStatistics(J9JFRThreadAllocationStatistics *threadAlocationData);
889+
882890
void addThreadObjectEntry(J9JFRThreadObject *tableEntry);
883891

884892
J9Pool *getExecutionSampleTable()
@@ -936,6 +944,11 @@ class VM_JFRConstantPoolTypes {
936944
return _classLoaderStatisticsTable;
937945
}
938946

947+
J9Pool *getThreadAllocationStatisticsTable()
948+
{
949+
return _threadAllocationStatisticsTable;
950+
}
951+
939952
J9Pool *getThreadContextSwitchRateTable()
940953
{
941954
return _threadContextSwitchRateTable;
@@ -1101,6 +1114,11 @@ class VM_JFRConstantPoolTypes {
11011114
return _classLoaderStatisticsCount;
11021115
}
11031116

1117+
UDATA getThreadAllocationStatisticsCount()
1118+
{
1119+
return _threadAllocationStatisticsCount;
1120+
}
1121+
11041122
UDATA getThreadContextSwitchRateCount()
11051123
{
11061124
return _threadContextSwitchRateCount;
@@ -1453,6 +1471,9 @@ class VM_JFRConstantPoolTypes {
14531471
case J9JFR_EVENT_TYPE_DATA_LOSS:
14541472
addDataLossEntry((J9JFRDataLoss *)event);
14551473
break;
1474+
case J9JFR_EVENT_TYPE_THREAD_ALLOCATION_STATISTICS:
1475+
addThreadAllocationStatistics((J9JFRThreadAllocationStatistics *)event);
1476+
break;
14561477
default:
14571478
Assert_VM_unreachable();
14581479
break;
@@ -1464,15 +1485,14 @@ class VM_JFRConstantPoolTypes {
14641485
goto done;
14651486
}
14661487

1467-
addAllThreads();
1468-
14691488
if (J9_ARE_NO_BITS_SET(_vm->extendedRuntimeFlags3, J9_EXTENDED_RUNTIME3_JFR_V2_SUPPORT)) {
14701489
if (dumpCalled) {
14711490
loadSystemProcesses(_currentThread);
14721491
loadNativeLibraries(_currentThread);
14731492
loadModuleRequireAndModuleExportEvents();
14741493
loadClassLoaderStatisticsEvents(_currentThread);
14751494
loadThreadDumpEvents(_currentThread);
1495+
loadThreadAllocationStatisticsEvents();
14761496
}
14771497
} else {
14781498
if (_shouldWriteSystemProcess) {
@@ -1489,6 +1509,8 @@ class VM_JFRConstantPoolTypes {
14891509
}
14901510
}
14911511

1512+
addAllThreads();
1513+
14921514
shallowEntries = pool_new(sizeof(ClassEntry **), 0, sizeof(U_64), 0, J9_GET_CALLSITE(), OMRMEM_CATEGORY_VM, POOL_FOR_PORT(privatePortLibrary));
14931515
if (NULL == shallowEntries) {
14941516
_buildResult = OutOfMemory;
@@ -2092,6 +2114,44 @@ class VM_JFRConstantPoolTypes {
20922114
return;
20932115
}
20942116

2117+
/**
2118+
* @brief Generate and add ThreadAllocationStatistics events to _threadAllocationStatisticsTable.
2119+
*/
2120+
void loadThreadAllocationStatisticsEvents()
2121+
{
2122+
int64_t time = j9time_nano_time();
2123+
J9InternalVMFunctions *vmFuncs = _vm->internalVMFunctions;
2124+
J9MemoryManagerFunctions *mmfns = _vm->memoryManagerFunctions;
2125+
2126+
Assert_VM_mustHaveVMAccess(_currentThread);
2127+
vmFuncs->acquireExclusiveVMAccess(_currentThread);
2128+
2129+
J9VMThread *walkThread = J9_LINKED_LIST_START_DO(_vm->mainThread);
2130+
2131+
while (NULL != walkThread) {
2132+
ThreadAllocationStatisticsEntry *entry = (ThreadAllocationStatisticsEntry *)pool_newElement(_threadAllocationStatisticsTable);
2133+
if (NULL == entry) {
2134+
_buildResult = OutOfMemory;
2135+
break;
2136+
}
2137+
memset(entry, 0, sizeof(*entry));
2138+
2139+
entry->ticks = time;
2140+
entry->threadIndex = getThreadTID(_currentThread, walkThread);
2141+
if (isResultNotOKay()) {
2142+
goto done;
2143+
}
2144+
UDATA allocated = 0;
2145+
mmfns->j9gc_get_cumulative_bytes_allocated_by_thread(walkThread, &allocated);
2146+
entry->allocated = (U_64)allocated;
2147+
2148+
_threadAllocationStatisticsCount += 1;
2149+
walkThread = J9_LINKED_LIST_NEXT_DO(_vm->mainThread, walkThread);
2150+
}
2151+
done:
2152+
vmFuncs->releaseExclusiveVMAccess(_currentThread);
2153+
}
2154+
20952155
VM_JFRConstantPoolTypes(J9VMThread *currentThread)
20962156
: _currentThread(currentThread)
20972157
, _vm(currentThread->javaVM)
@@ -2170,6 +2230,8 @@ class VM_JFRConstantPoolTypes {
21702230
, _dataLossCount(0)
21712231
, _threadDumpTable(NULL)
21722232
, _threadDumpCount(0)
2233+
, _threadAllocationStatisticsTable(NULL)
2234+
, _threadAllocationStatisticsCount(0)
21732235
, _shouldWriteJVMInformation(false)
21742236
, _shouldWriteCPUInformationEvent(false)
21752237
, _shouldWriteVirtualizationInformationEvent(false)
@@ -2326,6 +2388,12 @@ class VM_JFRConstantPoolTypes {
23262388
goto done;
23272389
}
23282390

2391+
_threadAllocationStatisticsTable = pool_new(sizeof(ThreadAllocationStatisticsEntry), 0, sizeof(U_64), 0, J9_GET_CALLSITE(), OMRMEM_CATEGORY_VM, POOL_FOR_PORT(privatePortLibrary));
2392+
if (NULL == _threadAllocationStatisticsTable) {
2393+
_buildResult = OutOfMemory;
2394+
goto done;
2395+
}
2396+
23292397
_threadContextSwitchRateTable = pool_new(sizeof(ThreadContextSwitchRateEntry), 0, sizeof(U_64), 0, J9_GET_CALLSITE(), OMRMEM_CATEGORY_VM, POOL_FOR_PORT(privatePortLibrary));
23302398
if (NULL == _threadContextSwitchRateTable) {
23312399
_buildResult = OutOfMemory;
@@ -2516,6 +2584,7 @@ class VM_JFRConstantPoolTypes {
25162584
pool_kill(_networkUtilizationTable);
25172585
pool_kill(_dataLossTable);
25182586
pool_kill(_threadDumpTable);
2587+
pool_kill(_threadAllocationStatisticsTable);
25192588
freeNetworkInterfaceNames();
25202589
j9mem_free_memory(_globalStringTable);
25212590
}

runtime/vm/JFRPeriodic.hpp

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -47,6 +47,7 @@ class JfrPeriodicEventSet {
4747
static void requestOSInformation(J9VMThread *currentThread);
4848
static void requestPhysicalMemory(J9VMThread *currentThread);
4949
static void requestSystemProcess(J9VMThread *currentThread);
50+
static void requestThreadAllocation(J9VMThread *currentThread);
5051
static void requestThreadContextSwitchRate(J9VMThread *currentThread);
5152
static void requestThreadCPULoad(J9VMThread *currentThread);
5253
static void requestThreadDump(J9VMThread *currentThread);

0 commit comments

Comments
 (0)