Skip to content

Commit

Permalink
Add JFR CPULoad and ThreadCPU event support
Browse files Browse the repository at this point in the history
Depends on: eclipse-omr/omr#7491

Signed-off-by: Gengchen Tuo <[email protected]>
  • Loading branch information
thallium committed Oct 31, 2024
1 parent 988c3b3 commit 3da4b50
Show file tree
Hide file tree
Showing 8 changed files with 326 additions and 0 deletions.
2 changes: 2 additions & 0 deletions runtime/oti/j9consts.h
Original file line number Diff line number Diff line change
Expand Up @@ -932,6 +932,8 @@ extern "C" {
#define J9JFR_EVENT_TYPE_THREAD_END 2
#define J9JFR_EVENT_TYPE_THREAD_SLEEP 3
#define J9JFR_EVENT_TYPE_OBJECT_WAIT 4
#define J9JFR_EVENT_TYPE_CPU_LOAD 5
#define J9JFR_EVENT_TYPE_THREAD_CPU_LOAD 6

/* JFR thread states */

Expand Down
24 changes: 24 additions & 0 deletions runtime/oti/j9nonbuilder.h
Original file line number Diff line number Diff line change
Expand Up @@ -345,6 +345,11 @@ struct J9VMContinuation;

#if defined(J9VM_OPT_JFR)

typedef struct J9VMThreadJFRState {
omrthread_thread_time_t prevThreadCPUTimes;
int64_t prevTimestamp;
} ThreadJFRState;

typedef struct J9JFRBufferWalkState {
U_8 *current;
U_8 *end;
Expand Down Expand Up @@ -414,6 +419,18 @@ typedef struct J9JFRMonitorWaited {
} J9JFRMonitorWaited;

#define J9JFRMonitorWaitedED_STACKTRACE(jfrEvent) ((UDATA*)(((J9JFRMonitorWaited*)(jfrEvent)) + 1))
typedef struct J9JFRCPULoad {
J9JFR_EVENT_COMMON_FIELDS
float jvmUser;
float jvmSystem;
float machineTotal;
} J9JFRCPULoad;

typedef struct J9JFRThreadCPULoad {
J9JFR_EVENT_COMMON_FIELDS
float user;
float system;
} J9JFRThreadCPULoad;

#endif /* defined(J9VM_OPT_JFR) */

Expand Down Expand Up @@ -5593,6 +5610,9 @@ typedef struct J9VMThread {
j9object_t closeScopeObj;
#endif /* JAVA_SPEC_VERSION >= 22 */
UDATA unsafeIndexableHeaderSize;
#if defined(J9VM_OPT_JFR)
ThreadJFRState threadJfrState;
#endif /* defined(J9VM_OPT_JFR) */
} J9VMThread;

#define J9VMTHREAD_ALIGNMENT 0x100
Expand Down Expand Up @@ -5671,6 +5691,9 @@ typedef struct JFRState {
BOOLEAN isConstantEventsInitialized;
BOOLEAN isStarted;
omrthread_monitor_t isConstantEventsInitializedMutex;
J9SysinfoCPUTime prevSysCPUTime;
omrthread_process_time_t prevProcCPUTimes;
int64_t prevProcTimestamp;
} JFRState;

typedef struct J9ReflectFunctionTable {
Expand Down Expand Up @@ -6210,6 +6233,7 @@ typedef struct J9JavaVM {
omrthread_t jfrSamplerThread;
UDATA jfrSamplerState;
IDATA jfrAsyncKey;
IDATA jfrThreadCPULoadAsyncKey;
#endif /* defined(J9VM_OPT_JFR) */
#if JAVA_SPEC_VERSION >= 22
omrthread_monitor_t closeScopeMutex;
Expand Down
7 changes: 7 additions & 0 deletions runtime/vm/BufferWriter.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -293,6 +293,13 @@ class VM_BufferWriter {
writeU8(((newVal >> 21) & 0x7F));
}

void
writeFloat(float val)
{
U_32 newVal = *(U_32 *)&val;
writeU32(newVal);
}

static U_32
convertFromLEB128ToU32(U_8 *start)
{
Expand Down
67 changes: 67 additions & 0 deletions runtime/vm/JFRChunkWriter.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -71,6 +71,8 @@ enum MetadataTypeID {
VirtualizationInformationID = 88,
InitialSystemPropertyID = 89,
CPUInformationID = 92,
CPULoadID = 94,
ThreadCPULoadID = 95,
PhysicalMemoryID = 107,
ExecutionSampleID = 108,
ThreadID = 163,
Expand Down Expand Up @@ -156,6 +158,8 @@ class VM_JFRChunkWriter {
static constexpr int CPU_INFORMATION_EVENT_SIZE = 600;
static constexpr int OS_INFORMATION_EVENT_SIZE = 100;
static constexpr int INITIAL_SYSTEM_PROPERTY_EVENT_SIZE = 6000;
static constexpr int CPU_LOAD_EVENT_SIZE = (3 * sizeof(float)) + (3 * sizeof(I_64));
static constexpr int THREAD_CPU_LOAD_EVENT_SIZE = (2 * sizeof(float)) + (4 * sizeof(I_64));

static constexpr int METADATA_ID = 1;

Expand Down Expand Up @@ -325,6 +329,9 @@ class VM_JFRChunkWriter {
pool_do(_constantPoolTypes.getThreadSleepTable(), &writeThreadSleepEvent, _bufferWriter);

pool_do(_constantPoolTypes.getMonitorWaitTable(), &writeMonitorWaitEvent, _bufferWriter);
pool_do(_constantPoolTypes.getCPULoadTable(), &writeCPULoadEvent, _bufferWriter);

pool_do(_constantPoolTypes.getThreadCPULoadTable(), &writeThreadCPULoadEvent, _bufferWriter);

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

static void
writeCPULoadEvent(void *anElement, void *userData)
{
CPULoadEntry *entry = (CPULoadEntry *)anElement;
VM_BufferWriter *_bufferWriter = (VM_BufferWriter *)userData;

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

_bufferWriter->writeLEB128(CPULoadID);

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

/* write user CPU load */
_bufferWriter->writeFloat(entry->jvmUser);

/* write system CPU load */
_bufferWriter->writeFloat(entry->jvmSystem);

/* write machine total CPU load */
_bufferWriter->writeFloat(entry->machineTotal);

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

static void
writeThreadCPULoadEvent(void *anElement, void *userData)
{
ThreadCPULoadEntry *entry = (ThreadCPULoadEntry *)anElement;
VM_BufferWriter *_bufferWriter = (VM_BufferWriter *)userData;

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

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

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

/* write thread index */
_bufferWriter->writeLEB128(entry->threadIndex);

/* write user thread CPU load */
_bufferWriter->writeFloat(entry->user);

/* write system thread CPU load */
_bufferWriter->writeFloat(entry->system);

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

void
writeJFRChunkToFile()
{
Expand Down Expand Up @@ -638,6 +700,11 @@ class VM_JFRChunkWriter {
requireBufferSize += CPU_INFORMATION_EVENT_SIZE;

requireBufferSize += INITIAL_SYSTEM_PROPERTY_EVENT_SIZE;

requireBufferSize += _constantPoolTypes.getCPULoadCount() * CPU_LOAD_EVENT_SIZE;

requireBufferSize += _constantPoolTypes.getThreadCPULoadCount() * THREAD_CPU_LOAD_EVENT_SIZE;

return requireBufferSize;
}

Expand Down
45 changes: 45 additions & 0 deletions runtime/vm/JFRConstantPoolTypes.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -1068,6 +1068,51 @@ VM_JFRConstantPoolTypes::addMonitorWaitEntry(J9JFRMonitorWaited* threadWaitData)
return index;
}

U_32
VM_JFRConstantPoolTypes::addCPULoadEntry(J9JFRCPULoad *cpuLoadData)
{
CPULoadEntry *entry = (CPULoadEntry *)pool_newElement(_cpuLoadTable);
U_32 index = U_32_MAX;

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

entry->ticks = cpuLoadData->startTicks;
entry->jvmUser = cpuLoadData->jvmUser;
entry->jvmSystem = cpuLoadData->jvmSystem;
entry->machineTotal = cpuLoadData->machineTotal;

index = _cpuLoadCount++;

done:
return index;
}

U_32
VM_JFRConstantPoolTypes::addThreadCPULoadEntry(J9JFRThreadCPULoad *threadCPULoadData)
{
ThreadCPULoadEntry *entry = (ThreadCPULoadEntry *)pool_newElement(_threadCPULoadTable);
U_32 index = U_32_MAX;

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

entry->ticks = threadCPULoadData->startTicks;
entry->user = threadCPULoadData->user;
entry->system = threadCPULoadData->system;

entry->threadIndex = addThreadEntry(threadCPULoadData->vmThread);
if (isResultNotOKay()) goto done;

index = _threadCPULoadCount++;

done:
return index;
}

void
VM_JFRConstantPoolTypes::printTables()
Expand Down
65 changes: 65 additions & 0 deletions runtime/vm/JFRConstantPoolTypes.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -212,6 +212,20 @@ struct StackTraceEntry {
StackTraceEntry *next;
};

struct CPULoadEntry {
I_64 ticks;
float jvmUser;
float jvmSystem;
float machineTotal;
};

struct ThreadCPULoadEntry {
I_64 ticks;
U_32 threadIndex;
float user;
float system;
};

struct JVMInformationEntry {
const char *jvmName;
const char *jvmVersion;
Expand Down Expand Up @@ -289,6 +303,10 @@ class VM_JFRConstantPoolTypes {
UDATA _threadSleepCount;
J9Pool *_monitorWaitTable;
UDATA _monitorWaitCount;
J9Pool *_cpuLoadTable;
UDATA _cpuLoadCount;
J9Pool *_threadCPULoadTable;
UDATA _threadCPULoadCount;

/* Processing buffers */
StackFrame *_currentStackFrameBuffer;
Expand Down Expand Up @@ -532,6 +550,10 @@ class VM_JFRConstantPoolTypes {

U_32 addMonitorWaitEntry(J9JFRMonitorWaited* threadWaitData);

U_32 addCPULoadEntry(J9JFRCPULoad *cpuLoadData);

U_32 addThreadCPULoadEntry(J9JFRThreadCPULoad *threadCPULoadData);

J9Pool *getExecutionSampleTable()
{
return _executionSampleTable;
Expand All @@ -557,6 +579,16 @@ class VM_JFRConstantPoolTypes {
return _monitorWaitTable;
}

J9Pool *getCPULoadTable()
{
return _cpuLoadTable;
}

J9Pool *getThreadCPULoadTable()
{
return _threadCPULoadTable;
}

UDATA getExecutionSampleCount()
{
return _executionSampleCount;
Expand All @@ -582,6 +614,16 @@ class VM_JFRConstantPoolTypes {
return _monitorWaitCount;
}

UDATA getCPULoadCount()
{
return _cpuLoadCount;
}

UDATA getThreadCPULoadCount()
{
return _threadCPULoadCount;
}

ClassloaderEntry *getClassloaderEntry()
{
return _firstClassloaderEntry;
Expand Down Expand Up @@ -723,6 +765,11 @@ class VM_JFRConstantPoolTypes {
break;
case J9JFR_EVENT_TYPE_OBJECT_WAIT:
addMonitorWaitEntry((J9JFRMonitorWaited*) event);
case J9JFR_EVENT_TYPE_CPU_LOAD:
addCPULoadEntry((J9JFRCPULoad *)event);
break;
case J9JFR_EVENT_TYPE_THREAD_CPU_LOAD:
addThreadCPULoadEntry((J9JFRThreadCPULoad *)event);
break;
default:
Assert_VM_unreachable();
Expand Down Expand Up @@ -1026,6 +1073,10 @@ class VM_JFRConstantPoolTypes {
, _threadSleepCount(0)
, _monitorWaitTable(NULL)
, _monitorWaitCount(0)
, _cpuLoadTable(NULL)
, _cpuLoadCount(0)
, _threadCPULoadTable(NULL)
, _threadCPULoadCount(0)
, _previousStackTraceEntry(NULL)
, _firstStackTraceEntry(NULL)
, _previousThreadEntry(NULL)
Expand Down Expand Up @@ -1128,6 +1179,18 @@ class VM_JFRConstantPoolTypes {
goto done;
}

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

_threadCPULoadTable = pool_new(sizeof(ThreadCPULoadEntry), 0, sizeof(U_64), 0, J9_GET_CALLSITE(), OMRMEM_CATEGORY_VM, POOL_FOR_PORT(privatePortLibrary));
if (NULL == _threadCPULoadTable) {
_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 @@ -1210,6 +1273,8 @@ class VM_JFRConstantPoolTypes {
pool_kill(_threadStartTable);
pool_kill(_threadEndTable);
pool_kill(_threadSleepTable);
pool_kill(_cpuLoadTable);
pool_kill(_threadCPULoadTable);
j9mem_free_memory(_globalStringTable);
}

Expand Down
Loading

0 comments on commit 3da4b50

Please sign in to comment.