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 11, 2024
1 parent 70f99fd commit 5b23512
Show file tree
Hide file tree
Showing 8 changed files with 333 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 @@ -931,6 +931,8 @@ extern "C" {
#define J9JFR_EVENT_TYPE_THREAD_START 1
#define J9JFR_EVENT_TYPE_THREAD_END 2
#define J9JFR_EVENT_TYPE_THREAD_SLEEP 3
#define J9JFR_EVENT_TYPE_CPU_LOAD 4
#define J9JFR_EVENT_TYPE_THREAD_CPU_LOAD 5

/* JFR thread states */

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

#if defined(J9VM_OPT_JFR)

typedef struct J9VMThreadJFRState {
U_64 prevUserTime;
U_64 prevSysTime;
I_64 prevTimestamp;
} ThreadJFRState;

typedef struct J9JFRBufferWalkState {
U_8 *current;
U_8 *end;
Expand Down Expand Up @@ -402,6 +408,19 @@ typedef struct J9JFRThreadSlept {

#define J9JFRTHREADSLEPT_STACKTRACE(jfrEvent) ((UDATA*)(((J9JFRThreadSlept*)(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) */

/* @ddr_namespace: map_to_type=J9CfrError */
Expand Down Expand Up @@ -5563,6 +5582,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 @@ -5640,6 +5662,9 @@ typedef struct JFRState {
void *constantEvents;
BOOLEAN isConstantEventsInitialized;
omrthread_monitor_t isConstantEventsInitializedMutex;
J9SysinfoCPUTime prevSysCPUTime;
omrthread_process_time_t prevProcCPUTime;
I_64 prevProcTimestamp;
} JFRState;

typedef struct J9ReflectFunctionTable {
Expand Down Expand Up @@ -6179,6 +6204,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
10 changes: 10 additions & 0 deletions runtime/vm/BufferWriter.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -293,6 +293,16 @@ class VM_BufferWriter {
writeU8(((newVal >> 21) & 0x7F));
}

void
writeFloat(float val)
{
U_32 newVal = *(U_32 *)&val;
if (_isLE) {
newVal = byteSwap(newVal);
}
writeData((U_8 *)&newVal, 4);
}

static U_32
convertFromLEB128ToU32(U_8 *start)
{
Expand Down
69 changes: 69 additions & 0 deletions runtime/vm/JFRChunkWriter.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -70,6 +70,8 @@ enum MetadataTypeID {
VirtualizationInformationID = 88,
InitialSystemPropertyID = 89,
CPUInformationID = 92,
CPULoadID = 94,
ThreadCPULoadID = 95,
PhysicalMemoryID = 107,
ExecutionSampleID = 108,
ThreadID = 163,
Expand Down Expand Up @@ -155,6 +157,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 @@ -323,6 +327,10 @@ class VM_JFRChunkWriter {

pool_do(_constantPoolTypes.getThreadSleepTable(), &writeThreadSleepEvent, _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) {
writeJVMInformationEvent();
Expand Down Expand Up @@ -477,6 +485,62 @@ 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));

/* write event type */
_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 @@ -590,6 +654,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 @@ -1031,6 +1031,51 @@ VM_JFRConstantPoolTypes::addThreadSleepEntry(J9JFRThreadSlept *threadSleepData)
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
66 changes: 66 additions & 0 deletions runtime/vm/JFRConstantPoolTypes.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -199,6 +199,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 @@ -274,6 +288,10 @@ class VM_JFRConstantPoolTypes {
UDATA _threadEndCount;
J9Pool *_threadSleepTable;
UDATA _threadSleepCount;
J9Pool *_cpuLoadTable;
UDATA _cpuLoadCount;
J9Pool *_threadCPULoadTable;
UDATA _threadCPULoadCount;

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

U_32 addThreadSleepEntry(J9JFRThreadSlept *threadSleepData);

U_32 addCPULoadEntry(J9JFRCPULoad *cpuLoadData);

U_32 addThreadCPULoadEntry(J9JFRThreadCPULoad *threadCPULoadData);

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

J9Pool *getCPULoadTable()
{
return _cpuLoadTable;
}

J9Pool *getThreadCPULoadTable()
{
return _threadCPULoadTable;
}

UDATA getExecutionSampleCount()
{
return _executionSampleCount;
Expand All @@ -555,6 +587,16 @@ class VM_JFRConstantPoolTypes {
return _threadSleepCount;
}

UDATA getCPULoadCount()
{
return _cpuLoadCount;
}

UDATA getThreadCPULoadCount()
{
return _threadCPULoadCount;
}

ClassloaderEntry *getClassloaderEntry()
{
return _firstClassloaderEntry;
Expand Down Expand Up @@ -694,6 +736,12 @@ class VM_JFRConstantPoolTypes {
case J9JFR_EVENT_TYPE_THREAD_SLEEP:
addThreadSleepEntry((J9JFRThreadSlept*) event);
break;
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();
break;
Expand Down Expand Up @@ -986,6 +1034,10 @@ class VM_JFRConstantPoolTypes {
, _threadEndCount(0)
, _threadSleepTable(NULL)
, _threadSleepCount(0)
, _cpuLoadTable(NULL)
, _cpuLoadCount(0)
, _threadCPULoadTable(NULL)
, _threadCPULoadCount(0)
, _previousStackTraceEntry(NULL)
, _firstStackTraceEntry(NULL)
, _previousThreadEntry(NULL)
Expand Down Expand Up @@ -1082,6 +1134,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 @@ -1161,6 +1225,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 5b23512

Please sign in to comment.