Skip to content

Commit

Permalink
Add JFR ThreadContextSwitchRate support
Browse files Browse the repository at this point in the history
Depends on: eclipse-omr/omr#7580

Signed-off-by: Gengchen Tuo <[email protected]>
  • Loading branch information
thallium committed Dec 11, 2024
1 parent e8707b4 commit 1f112d9
Show file tree
Hide file tree
Showing 7 changed files with 126 additions and 3 deletions.
1 change: 1 addition & 0 deletions runtime/oti/j9consts.h
Original file line number Diff line number Diff line change
Expand Up @@ -948,6 +948,7 @@ extern "C" {
#define J9JFR_EVENT_TYPE_CPU_LOAD 5
#define J9JFR_EVENT_TYPE_THREAD_CPU_LOAD 6
#define J9JFR_EVENT_TYPE_CLASS_LOADING_STATISTICS 7
#define J9JFR_EVENT_TYPE_THREAD_CONTEXT_SWITCH_RATE 8

/* JFR thread states */

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

typedef struct J9JFRThreadContextSwitchRate {
J9JFR_EVENT_COMMON_FIELDS
float switchRate;
} J9JFRThreadContextSwitchRate;

#endif /* defined(J9VM_OPT_JFR) */

/* @ddr_namespace: map_to_type=J9CfrError */
Expand Down Expand Up @@ -5715,6 +5720,8 @@ typedef struct JFRState {
J9SysinfoCPUTime prevSysCPUTime;
omrthread_process_time_t prevProcCPUTimes;
int64_t prevProcTimestamp;
int64_t prevContextSwitchTimestamp;
uint64_t prevContextSwitches;
} JFRState;

typedef struct J9ReflectFunctionTable {
Expand Down
23 changes: 23 additions & 0 deletions runtime/vm/JFRChunkWriter.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -888,4 +888,27 @@ VM_JFRChunkWriter::writeClassLoadingStatisticsEvent(void *anElement, void *userD
/* write size */
_bufferWriter->writeLEB128PaddedU32(dataStart, _bufferWriter->getCursor() - dataStart);
}

void
VM_JFRChunkWriter::writeThreadContextSwitchRateEvent(void *anElement, void *userData)
{
ThreadContextSwitchRateEntry *entry = (ThreadContextSwitchRateEntry *)anElement;
VM_BufferWriter *_bufferWriter = (VM_BufferWriter *)userData;

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

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

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

/* write switch rate */
_bufferWriter->writeFloat(entry->switchRate);

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

#endif /* defined(J9VM_OPT_JFR) */
6 changes: 6 additions & 0 deletions runtime/vm/JFRChunkWriter.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -74,6 +74,7 @@ enum MetadataTypeID {
CPUInformationID = 93,
CPULoadID = 95,
ThreadCPULoadID = 96,
ThreadContextSwitchRateID = 97,
ClassLoadingStatisticsID = 100,
PhysicalMemoryID = 108,
ExecutionSampleID = 109,
Expand Down Expand Up @@ -166,6 +167,7 @@ class VM_JFRChunkWriter {
static constexpr int THREAD_CPU_LOAD_EVENT_SIZE = (2 * sizeof(float)) + (4 * sizeof(I_64));
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 METADATA_ID = 1;

Expand Down Expand Up @@ -343,6 +345,8 @@ class VM_JFRChunkWriter {

pool_do(_constantPoolTypes.getClassLoadingStatisticsTable(), &writeClassLoadingStatisticsEvent, _bufferWriter);

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

/* Only write constant events in first chunk */
if (0 == _vm->jfrState.jfrChunkCount) {
writeJVMInformationEvent();
Expand Down Expand Up @@ -674,6 +678,8 @@ class VM_JFRChunkWriter {

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

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

UDATA
calculateRequiredBufferSize()
{
Expand Down
23 changes: 22 additions & 1 deletion runtime/vm/JFRConstantPoolTypes.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -23,6 +23,7 @@
#include "j9protos.h"
#include "j9consts.h"
#include "j9vmconstantpool.h"
#include "pool_api.h"

#if defined(J9VM_OPT_JFR)

Expand Down Expand Up @@ -1160,8 +1161,28 @@ VM_JFRConstantPoolTypes::addClassLoadingStatisticsEntry(J9JFRClassLoadingStatist
entry->loadedClassCount = classLoadingStatisticsData->loadedClassCount;
entry->unloadedClassCount = classLoadingStatisticsData->unloadedClassCount;

index = _classLoadingStatisticsCount;
index = (U_32)_classLoadingStatisticsCount;
_classLoadingStatisticsCount += 1;
done:
return index;
}

U_32
VM_JFRConstantPoolTypes::addThreadContextSwitchRateEntry(J9JFRThreadContextSwitchRate *threadContextSwitchRateData)
{
ThreadContextSwitchRateEntry *entry = (ThreadContextSwitchRateEntry *)pool_newElement(_threadContextSwitchRateTable);
U_32 index = U_32_MAX;

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

entry->ticks = threadContextSwitchRateData->startTicks;
entry->switchRate = threadContextSwitchRateData->switchRate;

index = _threadContextSwitchRateCount;
_threadContextSwitchRateCount += 1;

done:
return index;
Expand Down
31 changes: 31 additions & 0 deletions runtime/vm/JFRConstantPoolTypes.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -234,6 +234,11 @@ struct ClassLoadingStatisticsEntry {
I_64 unloadedClassCount;
};

struct ThreadContextSwitchRateEntry {
I_64 ticks;
float switchRate;
};

struct JVMInformationEntry {
const char *jvmName;
const char *jvmVersion;
Expand Down Expand Up @@ -317,6 +322,8 @@ class VM_JFRConstantPoolTypes {
UDATA _threadCPULoadCount;
J9Pool *_classLoadingStatisticsTable;
UDATA _classLoadingStatisticsCount;
J9Pool *_threadContextSwitchRateTable;
U_32 _threadContextSwitchRateCount;

/* Processing buffers */
StackFrame *_currentStackFrameBuffer;
Expand Down Expand Up @@ -586,6 +593,8 @@ class VM_JFRConstantPoolTypes {

U_32 addClassLoadingStatisticsEntry(J9JFRClassLoadingStatistics *classLoadingStatisticsData);

U_32 addThreadContextSwitchRateEntry(J9JFRThreadContextSwitchRate *threadContextSwitchRateData);

J9Pool *getExecutionSampleTable()
{
return _executionSampleTable;
Expand Down Expand Up @@ -626,6 +635,11 @@ class VM_JFRConstantPoolTypes {
return _classLoadingStatisticsTable;
}

J9Pool *getThreadContextSwitchRateTable()
{
return _threadContextSwitchRateTable;
}

UDATA getExecutionSampleCount()
{
return _executionSampleCount;
Expand Down Expand Up @@ -666,6 +680,11 @@ class VM_JFRConstantPoolTypes {
return _classLoadingStatisticsCount;
}

U_32 getThreadContextSwitchRateCount()
{
return _threadContextSwitchRateCount;
}

ClassloaderEntry *getClassloaderEntry()
{
return _firstClassloaderEntry;
Expand Down Expand Up @@ -818,6 +837,9 @@ class VM_JFRConstantPoolTypes {
case J9JFR_EVENT_TYPE_CLASS_LOADING_STATISTICS:
addClassLoadingStatisticsEntry((J9JFRClassLoadingStatistics *)event);
break;
case J9JFR_EVENT_TYPE_THREAD_CONTEXT_SWITCH_RATE:
addThreadContextSwitchRateEntry((J9JFRThreadContextSwitchRate *)event);
break;
default:
Assert_VM_unreachable();
break;
Expand Down Expand Up @@ -1143,6 +1165,8 @@ class VM_JFRConstantPoolTypes {
, _threadCPULoadCount(0)
, _classLoadingStatisticsTable(NULL)
, _classLoadingStatisticsCount(0)
, _threadContextSwitchRateTable(NULL)
, _threadContextSwitchRateCount(0)
, _previousStackTraceEntry(NULL)
, _firstStackTraceEntry(NULL)
, _previousThreadEntry(NULL)
Expand Down Expand Up @@ -1263,6 +1287,12 @@ class VM_JFRConstantPoolTypes {
goto done;
}

_threadContextSwitchRateTable = pool_new(sizeof(ThreadContextSwitchRateEntry), 0, sizeof(U_64), 0, J9_GET_CALLSITE(), OMRMEM_CATEGORY_VM, POOL_FOR_PORT(privatePortLibrary));
if (NULL == _threadContextSwitchRateTable ) {
_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 @@ -1352,6 +1382,7 @@ class VM_JFRConstantPoolTypes {
pool_kill(_cpuLoadTable);
pool_kill(_threadCPULoadTable);
pool_kill(_classLoadingStatisticsTable);
pool_kill(_threadContextSwitchRateTable);
j9mem_free_memory(_globalStringTable);
}

Expand Down
38 changes: 36 additions & 2 deletions runtime/vm/jfr.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -96,6 +96,9 @@ jfrEventSize(J9JFREvent *jfrEvent)
case J9JFR_EVENT_TYPE_CLASS_LOADING_STATISTICS:
size = sizeof(J9JFRClassLoadingStatistics);
break;
case J9JFR_EVENT_TYPE_THREAD_CONTEXT_SWITCH_RATE:
size = sizeof(J9JFRThreadContextSwitchRate);
break;
default:
Assert_VM_unreachable();
break;
Expand Down Expand Up @@ -719,6 +722,7 @@ initializeJFR(J9JavaVM *vm, BOOLEAN lateInit)

vm->jfrState.prevSysCPUTime.timestamp = -1;
vm->jfrState.prevProcTimestamp = -1;
vm->jfrState.prevContextSwitchTimestamp = -1;
if (omrthread_monitor_init_with_name(&vm->jfrBufferMutex, 0, "JFR global buffer mutex")) {
goto fail;
}
Expand Down Expand Up @@ -988,6 +992,35 @@ jfrClassLoadingStatistics(J9VMThread *currentThread)
}
}

void
jfrThreadContextSwitchRate(J9VMThread *currentThread)
{
PORT_ACCESS_FROM_VMC(currentThread);
OMRPORT_ACCESS_FROM_J9PORT(PORTLIB);

uint64_t switches;
int32_t rc = omrsysinfo_get_number_context_switches(&switches);

if (0 == rc) {
J9JFRThreadContextSwitchRate *jfrEvent = (J9JFRThreadContextSwitchRate *)reserveBuffer(currentThread, sizeof(J9JFRThreadContextSwitchRate));
if (NULL != jfrEvent) {
initializeEventFields(currentThread, (J9JFREvent *)jfrEvent, J9JFR_EVENT_TYPE_THREAD_CONTEXT_SWITCH_RATE);

JFRState *jfrState = &currentThread->javaVM->jfrState;
int64_t currentTime = j9time_nano_time();

if (-1 == jfrState->prevContextSwitchTimestamp) {
jfrEvent->switchRate = 0;
} else {
int64_t timeDelta = currentTime - jfrState->prevContextSwitchTimestamp;
jfrEvent->switchRate = ((double)(switches - jfrState->prevContextSwitches) / timeDelta) * 1e9;
}
jfrState->prevContextSwitches = switches;
jfrState->prevContextSwitchTimestamp = currentTime;
}
}
}

static int J9THREAD_PROC
jfrSamplingThreadProc(void *entryArg)
{
Expand All @@ -1006,11 +1039,12 @@ jfrSamplingThreadProc(void *entryArg)
internalAcquireVMAccess(currentThread);
jfrCPULoad(currentThread);
jfrClassLoadingStatistics(currentThread);
internalReleaseVMAccess(currentThread);
omrthread_monitor_enter(vm->jfrSamplerMutex);
if (0 == (count % 1000)) { // 10 seconds
J9SignalAsyncEvent(vm, NULL, vm->jfrThreadCPULoadAsyncKey);
jfrThreadContextSwitchRate(currentThread);
}
internalReleaseVMAccess(currentThread);
omrthread_monitor_enter(vm->jfrSamplerMutex);
}
count += 1;
omrthread_monitor_wait_timed(vm->jfrSamplerMutex, J9JFR_SAMPLING_RATE, 0);
Expand Down

0 comments on commit 1f112d9

Please sign in to comment.