Skip to content

Commit

Permalink
Adding in jfr thread stat event and fixes for thread park.
Browse files Browse the repository at this point in the history
  • Loading branch information
adpopescu committed Jan 16, 2025
1 parent 30f423a commit 3852b3a
Show file tree
Hide file tree
Showing 8 changed files with 146 additions and 7 deletions.
1 change: 1 addition & 0 deletions runtime/oti/j9consts.h
Original file line number Diff line number Diff line change
Expand Up @@ -953,6 +953,7 @@ extern "C" {
#define J9JFR_EVENT_TYPE_CLASS_LOADING_STATISTICS 7
#define J9JFR_EVENT_TYPE_THREAD_CONTEXT_SWITCH_RATE 8
#define J9JFR_EVENT_TYPE_THREAD_PARK 9
#define J9JFR_EVENT_TYPE_THREAD_STATISTICS 10

/* JFR thread states */

Expand Down
10 changes: 10 additions & 0 deletions runtime/oti/j9nonbuilder.h
Original file line number Diff line number Diff line change
Expand Up @@ -453,6 +453,14 @@ typedef struct J9JFRClassLoadingStatistics {
I_64 unloadedClassCount;
} J9JFRClassLoadingStatistics;

typedef struct J9JFRThreadStatistics {
J9JFR_EVENT_COMMON_FIELDS
U_32 activeThreadCount;
U_32 daemonThreadCount;
U_32 accumulatedThreadCount;
U_32 peakThreadCount;
} J9JFRThreadStatistics;

typedef struct J9JFRThreadContextSwitchRate {
J9JFR_EVENT_COMMON_FIELDS
float switchRate;
Expand Down Expand Up @@ -5873,6 +5881,8 @@ typedef struct J9JavaVM {
UDATA anonClassCount;
UDATA totalThreadCount;
UDATA daemonThreadCount;
UDATA accumulatedThreadCount;
UDATA peakThreadCount;
omrthread_t finalizeMainThread;
omrthread_monitor_t finalizeMainMonitor;
omrthread_monitor_t processReferenceMonitor; /* the monitor for synchronizing between reference process and j9gc_wait_for_reference_processing() (only for Java 9 and later) */
Expand Down
31 changes: 31 additions & 0 deletions runtime/vm/JFRChunkWriter.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -911,4 +911,35 @@ VM_JFRChunkWriter::writeThreadContextSwitchRateEvent(void *anElement, void *user
_bufferWriter->writeLEB128PaddedU32(dataStart, (U_32)(_bufferWriter->getCursor() - dataStart));
}

void
VM_JFRChunkWriter::writeThreadStatisticsEvent(void *anElement, void *userData)
{
ThreadStatisticsEntry *entry = (ThreadStatisticsEntry *)anElement;
VM_BufferWriter *_bufferWriter = (VM_BufferWriter *)userData;

/* reserve event size */
U_8 *dataStart = _bufferWriter->getAndIncCursor(sizeof(U_32));

/* write event type */
_bufferWriter->writeLEB128(ThreadStatisticsID);

/* write start ticks */
_bufferWriter->writeLEB128(entry->ticks);

/* write active thread count */
_bufferWriter->writeLEB128(entry->activeThreadCount);

/* write daemon thread count */
_bufferWriter->writeLEB128(entry->daemonThreadCount);

/* write accumulated thread count */
_bufferWriter->writeLEB128(entry->accumulatedThreadCount);

/* write peak thread count */
_bufferWriter->writeLEB128(entry->peakThreadCount);

/* write size */
_bufferWriter->writeLEB128PaddedU32(dataStart, _bufferWriter->getCursor() - dataStart);
}

#endif /* defined(J9VM_OPT_JFR) */
13 changes: 11 additions & 2 deletions runtime/vm/JFRChunkWriter.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -76,6 +76,7 @@ enum MetadataTypeID {
CPULoadID = 95,
ThreadCPULoadID = 96,
ThreadContextSwitchRateID = 97,
ThreadStatisticsID = 99,
ClassLoadingStatisticsID = 100,
PhysicalMemoryID = 108,
ExecutionSampleID = 109,
Expand Down Expand Up @@ -158,6 +159,7 @@ class VM_JFRChunkWriter {
static constexpr int THREAD_END_EVENT_SIZE = (4 * sizeof(U_64)) + sizeof(U_32);
static constexpr int THREAD_SLEEP_EVENT_SIZE = (7 * sizeof(U_64)) + sizeof(U_32);
static constexpr int MONITOR_WAIT_EVENT_SIZE = (9 * sizeof(U_64)) + sizeof(U_32);
static constexpr int THREAD_PARK_EVENT_SIZE = sizeof(ThreadParkEntry);
static constexpr int JVM_INFORMATION_EVENT_SIZE = 3000;
static constexpr int PHYSICAL_MEMORY_EVENT_SIZE = (4 * sizeof(U_64)) + sizeof(U_32);
static constexpr int VIRTUALIZATION_INFORMATION_EVENT_SIZE = 50;
Expand All @@ -169,6 +171,7 @@ class VM_JFRChunkWriter {
static constexpr int INITIAL_ENVIRONMENT_VARIABLE_EVENT_SIZE = 6000;
static constexpr int CLASS_LOADING_STATISTICS_EVENT_SIZE = 5 * sizeof(I_64);
static constexpr int THREAD_CONTEXT_SWITCH_RATE_SIZE = sizeof(float) + (3 * sizeof(I_64));
static constexpr int THREAD_STATISTICS_EVENT_SIZE = sizeof(ThreadStatisticsEntry);

static constexpr int METADATA_ID = 1;

Expand Down Expand Up @@ -350,6 +353,8 @@ class VM_JFRChunkWriter {

pool_do(_constantPoolTypes.getThreadContextSwitchRateTable(), &writeThreadContextSwitchRateEvent, _bufferWriter);

pool_do(_constantPoolTypes.getThreadStatisticsTable(), &writeThreadStatisticsEvent, _bufferWriter);

/* Only write constant events in first chunk */
if (0 == _vm->jfrState.jfrChunkCount) {
writeJVMInformationEvent();
Expand Down Expand Up @@ -597,7 +602,6 @@ class VM_JFRChunkWriter {
_bufferWriter->writeLEB128PaddedU32(dataStart, _bufferWriter->getCursor() - dataStart);
}


static void
writeCPULoadEvent(void *anElement, void *userData)
{
Expand Down Expand Up @@ -653,7 +657,6 @@ class VM_JFRChunkWriter {
/* write size */
_bufferWriter->writeLEB128PaddedU32(dataStart, _bufferWriter->getCursor() - dataStart);
}

void
writeJFRChunkToFile()
{
Expand Down Expand Up @@ -726,6 +729,8 @@ class VM_JFRChunkWriter {

static void writeThreadContextSwitchRateEvent(void *anElement, void *userData);

static void writeThreadStatisticsEvent(void *anElement, void *userData);

UDATA
calculateRequiredBufferSize()
{
Expand Down Expand Up @@ -768,6 +773,8 @@ class VM_JFRChunkWriter {

requiredBufferSize += (_constantPoolTypes.getMonitorWaitCount() * MONITOR_WAIT_EVENT_SIZE);

requiredBufferSize += (_constantPoolTypes.getThreadParkCount() * THREAD_PARK_EVENT_SIZE);

requiredBufferSize += JVM_INFORMATION_EVENT_SIZE;

requiredBufferSize += OS_INFORMATION_EVENT_SIZE;
Expand All @@ -790,6 +797,8 @@ class VM_JFRChunkWriter {

requiredBufferSize += _constantPoolTypes.getThreadContextSwitchRateCount() * THREAD_CONTEXT_SWITCH_RATE_SIZE;

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

return requiredBufferSize;
}

Expand Down
32 changes: 30 additions & 2 deletions runtime/vm/JFRConstantPoolTypes.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -1096,10 +1096,11 @@ VM_JFRConstantPoolTypes::addMonitorWaitEntry(J9JFRMonitorWaited* threadWaitData)
return index;
}

void
U_32
VM_JFRConstantPoolTypes::addThreadParkEntry(J9JFRThreadParked* threadParkData)
{
ThreadParkEntry *entry = (ThreadParkEntry*)pool_newElement(_threadParkTable);
U_32 index = U_32_MAX;

if (NULL == entry) {
_buildResult = OutOfMemory;
Expand All @@ -1126,8 +1127,11 @@ VM_JFRConstantPoolTypes::addThreadParkEntry(J9JFRThreadParked* threadParkData)
entry->timeOut = threadParkData->timeOut;
entry->untilTime = threadParkData->untilTime;

index = _threadParkCount;
++(_threadParkCount);

done:
return;
return index;
}

U_32
Expand Down Expand Up @@ -1217,6 +1221,30 @@ VM_JFRConstantPoolTypes::addThreadContextSwitchRateEntry(J9JFRThreadContextSwitc
_threadContextSwitchRateCount += 1;
}

U_32
VM_JFRConstantPoolTypes::addThreadStatisticsEntry(J9JFRThreadStatistics *threadStatisticsData)
{
ThreadStatisticsEntry *entry = (ThreadStatisticsEntry *)pool_newElement(_threadStatisticsTable);
U_32 index = U_32_MAX;

if (NULL == entry) {
_buildResult = OutOfMemory;
goto done;
}

entry->ticks = threadStatisticsData->startTicks;
entry->activeThreadCount = threadStatisticsData->activeThreadCount;
entry->daemonThreadCount = threadStatisticsData->daemonThreadCount;
entry->accumulatedThreadCount = threadStatisticsData->accumulatedThreadCount;
entry->peakThreadCount = threadStatisticsData->peakThreadCount;

index = _threadStatisticsCount;
++(_threadStatisticsCount);

done:
return index;
}

void
VM_JFRConstantPoolTypes::printTables()
{
Expand Down
40 changes: 37 additions & 3 deletions runtime/vm/JFRConstantPoolTypes.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -251,6 +251,14 @@ struct ThreadContextSwitchRateEntry {
float switchRate;
};

struct ThreadStatisticsEntry {
I_64 ticks;
U_32 activeThreadCount;
U_32 daemonThreadCount;
U_32 accumulatedThreadCount;
U_32 peakThreadCount;
};

struct JVMInformationEntry {
const char *jvmName;
const char *jvmVersion;
Expand Down Expand Up @@ -329,7 +337,7 @@ class VM_JFRConstantPoolTypes {
J9Pool *_monitorWaitTable;
UDATA _monitorWaitCount;
J9Pool *_threadParkTable;
UDATA _threadParkCount;
U_32 _threadParkCount;
J9Pool *_cpuLoadTable;
UDATA _cpuLoadCount;
J9Pool *_threadCPULoadTable;
Expand All @@ -338,6 +346,8 @@ class VM_JFRConstantPoolTypes {
UDATA _classLoadingStatisticsCount;
J9Pool *_threadContextSwitchRateTable;
U_32 _threadContextSwitchRateCount;
J9Pool *_threadStatisticsTable;
U_32 _threadStatisticsCount;

/* Processing buffers */
StackFrame *_currentStackFrameBuffer;
Expand Down Expand Up @@ -601,7 +611,7 @@ class VM_JFRConstantPoolTypes {

U_32 addMonitorWaitEntry(J9JFRMonitorWaited* threadWaitData);

void addThreadParkEntry(J9JFRThreadParked* threadParkData);
U_32 addThreadParkEntry(J9JFRThreadParked* threadParkData);

U_32 addCPULoadEntry(J9JFRCPULoad *cpuLoadData);

Expand All @@ -611,6 +621,8 @@ class VM_JFRConstantPoolTypes {

void addThreadContextSwitchRateEntry(J9JFRThreadContextSwitchRate *threadContextSwitchRateData);

U_32 addThreadStatisticsEntry(J9JFRThreadStatistics *threadStatisticsData);

J9Pool *getExecutionSampleTable()
{
return _executionSampleTable;
Expand Down Expand Up @@ -661,6 +673,11 @@ class VM_JFRConstantPoolTypes {
return _threadContextSwitchRateTable;
}

J9Pool *getThreadStatisticsTable()
{
return _threadStatisticsTable;
}

UDATA getExecutionSampleCount()
{
return _executionSampleCount;
Expand All @@ -686,7 +703,7 @@ class VM_JFRConstantPoolTypes {
return _monitorWaitCount;
}

UDATA getThreadParkCount()
U_32 getThreadParkCount()
{
return _threadParkCount;
}
Expand All @@ -711,6 +728,11 @@ class VM_JFRConstantPoolTypes {
return _threadContextSwitchRateCount;
}

U_32 getThreadStatisticsCount()
{
return _threadStatisticsCount;
}

ClassloaderEntry *getClassloaderEntry()
{
return _firstClassloaderEntry;
Expand Down Expand Up @@ -869,6 +891,9 @@ class VM_JFRConstantPoolTypes {
case J9JFR_EVENT_TYPE_THREAD_CONTEXT_SWITCH_RATE:
addThreadContextSwitchRateEntry((J9JFRThreadContextSwitchRate *)event);
break;
case J9JFR_EVENT_TYPE_THREAD_STATISTICS:
addThreadStatisticsEntry((J9JFRThreadStatistics *)event);
break;
default:
Assert_VM_unreachable();
break;
Expand Down Expand Up @@ -1201,6 +1226,8 @@ class VM_JFRConstantPoolTypes {
, _classLoadingStatisticsCount(0)
, _threadContextSwitchRateTable(NULL)
, _threadContextSwitchRateCount(0)
, _threadStatisticsTable(NULL)
, _threadStatisticsCount(0)
, _previousStackTraceEntry(NULL)
, _firstStackTraceEntry(NULL)
, _previousThreadEntry(NULL)
Expand Down Expand Up @@ -1333,6 +1360,12 @@ class VM_JFRConstantPoolTypes {
goto done;
}

_threadStatisticsTable = pool_new(sizeof(ThreadStatisticsEntry), 0, sizeof(U_64), 0, J9_GET_CALLSITE(), OMRMEM_CATEGORY_VM, POOL_FOR_PORT(privatePortLibrary));
if (NULL == _threadStatisticsTable ) {
_buildResult = OutOfMemory;
goto done;
}

/* Add reserved index for default entries. For strings zero is the empty or NUll string.
* For package zero is the deafult package, for Module zero is the unnamed module. ThreadGroup
* zero is NULL threadGroup.
Expand Down Expand Up @@ -1424,6 +1457,7 @@ class VM_JFRConstantPoolTypes {
pool_kill(_threadCPULoadTable);
pool_kill(_classLoadingStatisticsTable);
pool_kill(_threadContextSwitchRateTable);
pool_kill(_threadStatisticsTable);
j9mem_free_memory(_globalStringTable);
}

Expand Down
21 changes: 21 additions & 0 deletions runtime/vm/jfr.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -103,6 +103,9 @@ jfrEventSize(J9JFREvent *jfrEvent)
case J9JFR_EVENT_TYPE_THREAD_CONTEXT_SWITCH_RATE:
size = sizeof(J9JFRThreadContextSwitchRate);
break;
case J9JFR_EVENT_TYPE_THREAD_STATISTICS:
size = sizeof(J9JFRThreadStatistics);
break;
default:
Assert_VM_unreachable();
break;
Expand Down Expand Up @@ -1078,6 +1081,23 @@ jfrThreadContextSwitchRate(J9VMThread *currentThread)
}
}

void
jfrThreadStatistics(J9VMThread *currentThread)
{
J9JavaVM *vm = currentThread->javaVM;
J9JFRThreadStatistics *jfrEvent = (J9JFRThreadStatistics *)reserveBuffer(currentThread, sizeof(J9JFRThreadStatistics));

if (NULL != jfrEvent) {
initializeEventFields(currentThread, (J9JFREvent *)jfrEvent, J9JFR_EVENT_TYPE_THREAD_STATISTICS);

jfrEvent->activeThreadCount = vm->totalThreadCount;
jfrEvent->daemonThreadCount = vm->daemonThreadCount;
jfrEvent->accumulatedThreadCount = vm->accumulatedThreadCount;
jfrEvent->peakThreadCount = vm->peakThreadCount;
}

}

static int J9THREAD_PROC
jfrSamplingThreadProc(void *entryArg)
{
Expand All @@ -1096,6 +1116,7 @@ jfrSamplingThreadProc(void *entryArg)
internalAcquireVMAccess(currentThread);
jfrCPULoad(currentThread);
jfrClassLoadingStatistics(currentThread);
jfrThreadStatistics(currentThread);
if (0 == (count % 1000)) { // 10 seconds
J9SignalAsyncEvent(vm, NULL, vm->jfrThreadCPULoadAsyncKey);
jfrThreadContextSwitchRate(currentThread);
Expand Down
5 changes: 5 additions & 0 deletions runtime/vm/vmthread.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -348,6 +348,11 @@ allocateVMThread(J9JavaVM *vm, omrthread_t osThread, UDATA privateFlags, void *m
/* Update counters for total # of threads and daemon threads and notify anyone waiting */

++(vm->totalThreadCount);
++(vm->accumulatedThreadCount);
if (vm->totalThreadCount > vm->peakThreadCount) {
vm->peakThreadCount = vm->totalThreadCount;
}

if (privateFlags & J9_PRIVATE_FLAGS_DAEMON_THREAD) {
++(vm->daemonThreadCount);
}
Expand Down

0 comments on commit 3852b3a

Please sign in to comment.