Skip to content

Commit b15f557

Browse files
committed
Add JFR ThreadContextSwitchRate support
Depends on: eclipse-omr/omr#7580 Signed-off-by: Gengchen Tuo <gengchen.tuo@ibm.com>
1 parent e8707b4 commit b15f557

7 files changed

+123
-3
lines changed

runtime/oti/j9consts.h

+1
Original file line numberDiff line numberDiff line change
@@ -948,6 +948,7 @@ extern "C" {
948948
#define J9JFR_EVENT_TYPE_CPU_LOAD 5
949949
#define J9JFR_EVENT_TYPE_THREAD_CPU_LOAD 6
950950
#define J9JFR_EVENT_TYPE_CLASS_LOADING_STATISTICS 7
951+
#define J9JFR_EVENT_TYPE_THREAD_CONTEXT_SWITCH_RATE 8
951952

952953
/* JFR thread states */
953954

runtime/oti/j9nonbuilder.h

+7
Original file line numberDiff line numberDiff line change
@@ -440,6 +440,11 @@ typedef struct J9JFRClassLoadingStatistics {
440440
I_64 unloadedClassCount;
441441
} J9JFRClassLoadingStatistics;
442442

443+
typedef struct J9JFRThreadContextSwitchRate {
444+
J9JFR_EVENT_COMMON_FIELDS
445+
float switchRate;
446+
} J9JFRThreadContextSwitchRate;
447+
443448
#endif /* defined(J9VM_OPT_JFR) */
444449

445450
/* @ddr_namespace: map_to_type=J9CfrError */
@@ -5715,6 +5720,8 @@ typedef struct JFRState {
57155720
J9SysinfoCPUTime prevSysCPUTime;
57165721
omrthread_process_time_t prevProcCPUTimes;
57175722
int64_t prevProcTimestamp;
5723+
int64_t prevContextSwitchTimestamp;
5724+
uint64_t prevContextSwitches;
57185725
} JFRState;
57195726

57205727
typedef struct J9ReflectFunctionTable {

runtime/vm/JFRChunkWriter.cpp

+23
Original file line numberDiff line numberDiff line change
@@ -888,4 +888,27 @@ VM_JFRChunkWriter::writeClassLoadingStatisticsEvent(void *anElement, void *userD
888888
/* write size */
889889
_bufferWriter->writeLEB128PaddedU32(dataStart, _bufferWriter->getCursor() - dataStart);
890890
}
891+
892+
void
893+
VM_JFRChunkWriter::writeThreadContextSwitchRateEvent(void *anElement, void *userData)
894+
{
895+
ThreadContextSwitchRateEntry *entry = (ThreadContextSwitchRateEntry *)anElement;
896+
VM_BufferWriter *_bufferWriter = (VM_BufferWriter *)userData;
897+
898+
/* reserve size field */
899+
U_8 *dataStart = _bufferWriter->getAndIncCursor(sizeof(U_32));
900+
901+
/* write event type */
902+
_bufferWriter->writeLEB128(ThreadContextSwitchRateID);
903+
904+
/* write start time */
905+
_bufferWriter->writeLEB128(entry->ticks);
906+
907+
/* write switch rate */
908+
_bufferWriter->writeFloat(entry->switchRate);
909+
910+
/* write size */
911+
_bufferWriter->writeLEB128PaddedU32(dataStart, (U_32)(_bufferWriter->getCursor() - dataStart));
912+
}
913+
891914
#endif /* defined(J9VM_OPT_JFR) */

runtime/vm/JFRChunkWriter.hpp

+8
Original file line numberDiff line numberDiff line change
@@ -74,6 +74,7 @@ enum MetadataTypeID {
7474
CPUInformationID = 93,
7575
CPULoadID = 95,
7676
ThreadCPULoadID = 96,
77+
ThreadContextSwitchRateID = 97,
7778
ClassLoadingStatisticsID = 100,
7879
PhysicalMemoryID = 108,
7980
ExecutionSampleID = 109,
@@ -166,6 +167,7 @@ class VM_JFRChunkWriter {
166167
static constexpr int THREAD_CPU_LOAD_EVENT_SIZE = (2 * sizeof(float)) + (4 * sizeof(I_64));
167168
static constexpr int INITIAL_ENVIRONMENT_VARIABLE_EVENT_SIZE = 6000;
168169
static constexpr int CLASS_LOADING_STATISTICS_EVENT_SIZE = 5 * sizeof(I_64);
170+
static constexpr int THREAD_CONTEXT_SWITCH_RATE_SIZE = sizeof(float) + (3 * sizeof(I_64));
169171

170172
static constexpr int METADATA_ID = 1;
171173

@@ -343,6 +345,8 @@ class VM_JFRChunkWriter {
343345

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

348+
pool_do(_constantPoolTypes.getThreadContextSwitchRateTable(), &writeThreadContextSwitchRateEvent, _bufferWriter);
349+
346350
/* Only write constant events in first chunk */
347351
if (0 == _vm->jfrState.jfrChunkCount) {
348352
writeJVMInformationEvent();
@@ -674,6 +678,8 @@ class VM_JFRChunkWriter {
674678

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

681+
static void writeThreadContextSwitchRateEvent(void *anElement, void *userData);
682+
677683
UDATA
678684
calculateRequiredBufferSize()
679685
{
@@ -736,6 +742,8 @@ class VM_JFRChunkWriter {
736742

737743
requiredBufferSize += _constantPoolTypes.getClassLoadingStatisticsCount() * CLASS_LOADING_STATISTICS_EVENT_SIZE;
738744

745+
requiredBufferSize += _constantPoolTypes.getThreadContextSwitchRateCount() * THREAD_CONTEXT_SWITCH_RATE_SIZE;
746+
739747
return requiredBufferSize;
740748
}
741749

runtime/vm/JFRConstantPoolTypes.cpp

+17-1
Original file line numberDiff line numberDiff line change
@@ -23,6 +23,7 @@
2323
#include "j9protos.h"
2424
#include "j9consts.h"
2525
#include "j9vmconstantpool.h"
26+
#include "pool_api.h"
2627

2728
#if defined(J9VM_OPT_JFR)
2829

@@ -1162,11 +1163,26 @@ VM_JFRConstantPoolTypes::addClassLoadingStatisticsEntry(J9JFRClassLoadingStatist
11621163

11631164
index = _classLoadingStatisticsCount;
11641165
_classLoadingStatisticsCount += 1;
1165-
11661166
done:
11671167
return index;
11681168
}
11691169

1170+
void
1171+
VM_JFRConstantPoolTypes::addThreadContextSwitchRateEntry(J9JFRThreadContextSwitchRate *threadContextSwitchRateData)
1172+
{
1173+
ThreadContextSwitchRateEntry *entry = (ThreadContextSwitchRateEntry *)pool_newElement(_threadContextSwitchRateTable);
1174+
1175+
if (NULL == entry) {
1176+
_buildResult = OutOfMemory;
1177+
return;
1178+
}
1179+
1180+
entry->ticks = threadContextSwitchRateData->startTicks;
1181+
entry->switchRate = threadContextSwitchRateData->switchRate;
1182+
1183+
_threadContextSwitchRateCount += 1;
1184+
}
1185+
11701186
void
11711187
VM_JFRConstantPoolTypes::printTables()
11721188
{

runtime/vm/JFRConstantPoolTypes.hpp

+31
Original file line numberDiff line numberDiff line change
@@ -234,6 +234,11 @@ struct ClassLoadingStatisticsEntry {
234234
I_64 unloadedClassCount;
235235
};
236236

237+
struct ThreadContextSwitchRateEntry {
238+
I_64 ticks;
239+
float switchRate;
240+
};
241+
237242
struct JVMInformationEntry {
238243
const char *jvmName;
239244
const char *jvmVersion;
@@ -317,6 +322,8 @@ class VM_JFRConstantPoolTypes {
317322
UDATA _threadCPULoadCount;
318323
J9Pool *_classLoadingStatisticsTable;
319324
UDATA _classLoadingStatisticsCount;
325+
J9Pool *_threadContextSwitchRateTable;
326+
U_32 _threadContextSwitchRateCount;
320327

321328
/* Processing buffers */
322329
StackFrame *_currentStackFrameBuffer;
@@ -586,6 +593,8 @@ class VM_JFRConstantPoolTypes {
586593

587594
U_32 addClassLoadingStatisticsEntry(J9JFRClassLoadingStatistics *classLoadingStatisticsData);
588595

596+
void addThreadContextSwitchRateEntry(J9JFRThreadContextSwitchRate *threadContextSwitchRateData);
597+
589598
J9Pool *getExecutionSampleTable()
590599
{
591600
return _executionSampleTable;
@@ -626,6 +635,11 @@ class VM_JFRConstantPoolTypes {
626635
return _classLoadingStatisticsTable;
627636
}
628637

638+
J9Pool *getThreadContextSwitchRateTable()
639+
{
640+
return _threadContextSwitchRateTable;
641+
}
642+
629643
UDATA getExecutionSampleCount()
630644
{
631645
return _executionSampleCount;
@@ -666,6 +680,11 @@ class VM_JFRConstantPoolTypes {
666680
return _classLoadingStatisticsCount;
667681
}
668682

683+
U_32 getThreadContextSwitchRateCount()
684+
{
685+
return _threadContextSwitchRateCount;
686+
}
687+
669688
ClassloaderEntry *getClassloaderEntry()
670689
{
671690
return _firstClassloaderEntry;
@@ -818,6 +837,9 @@ class VM_JFRConstantPoolTypes {
818837
case J9JFR_EVENT_TYPE_CLASS_LOADING_STATISTICS:
819838
addClassLoadingStatisticsEntry((J9JFRClassLoadingStatistics *)event);
820839
break;
840+
case J9JFR_EVENT_TYPE_THREAD_CONTEXT_SWITCH_RATE:
841+
addThreadContextSwitchRateEntry((J9JFRThreadContextSwitchRate *)event);
842+
break;
821843
default:
822844
Assert_VM_unreachable();
823845
break;
@@ -1143,6 +1165,8 @@ class VM_JFRConstantPoolTypes {
11431165
, _threadCPULoadCount(0)
11441166
, _classLoadingStatisticsTable(NULL)
11451167
, _classLoadingStatisticsCount(0)
1168+
, _threadContextSwitchRateTable(NULL)
1169+
, _threadContextSwitchRateCount(0)
11461170
, _previousStackTraceEntry(NULL)
11471171
, _firstStackTraceEntry(NULL)
11481172
, _previousThreadEntry(NULL)
@@ -1263,6 +1287,12 @@ class VM_JFRConstantPoolTypes {
12631287
goto done;
12641288
}
12651289

1290+
_threadContextSwitchRateTable = pool_new(sizeof(ThreadContextSwitchRateEntry), 0, sizeof(U_64), 0, J9_GET_CALLSITE(), OMRMEM_CATEGORY_VM, POOL_FOR_PORT(privatePortLibrary));
1291+
if (NULL == _threadContextSwitchRateTable ) {
1292+
_buildResult = OutOfMemory;
1293+
goto done;
1294+
}
1295+
12661296
/* Add reserved index for default entries. For strings zero is the empty or NUll string.
12671297
* For package zero is the deafult package, for Module zero is the unnamed module. ThreadGroup
12681298
* zero is NULL threadGroup.
@@ -1352,6 +1382,7 @@ class VM_JFRConstantPoolTypes {
13521382
pool_kill(_cpuLoadTable);
13531383
pool_kill(_threadCPULoadTable);
13541384
pool_kill(_classLoadingStatisticsTable);
1385+
pool_kill(_threadContextSwitchRateTable);
13551386
j9mem_free_memory(_globalStringTable);
13561387
}
13571388

runtime/vm/jfr.cpp

+36-2
Original file line numberDiff line numberDiff line change
@@ -96,6 +96,9 @@ jfrEventSize(J9JFREvent *jfrEvent)
9696
case J9JFR_EVENT_TYPE_CLASS_LOADING_STATISTICS:
9797
size = sizeof(J9JFRClassLoadingStatistics);
9898
break;
99+
case J9JFR_EVENT_TYPE_THREAD_CONTEXT_SWITCH_RATE:
100+
size = sizeof(J9JFRThreadContextSwitchRate);
101+
break;
99102
default:
100103
Assert_VM_unreachable();
101104
break;
@@ -719,6 +722,7 @@ initializeJFR(J9JavaVM *vm, BOOLEAN lateInit)
719722

720723
vm->jfrState.prevSysCPUTime.timestamp = -1;
721724
vm->jfrState.prevProcTimestamp = -1;
725+
vm->jfrState.prevContextSwitchTimestamp = -1;
722726
if (omrthread_monitor_init_with_name(&vm->jfrBufferMutex, 0, "JFR global buffer mutex")) {
723727
goto fail;
724728
}
@@ -988,6 +992,35 @@ jfrClassLoadingStatistics(J9VMThread *currentThread)
988992
}
989993
}
990994

995+
void
996+
jfrThreadContextSwitchRate(J9VMThread *currentThread)
997+
{
998+
PORT_ACCESS_FROM_VMC(currentThread);
999+
OMRPORT_ACCESS_FROM_J9PORT(PORTLIB);
1000+
1001+
uint64_t switches = 0;
1002+
int32_t rc = omrsysinfo_get_number_context_switches(&switches);
1003+
1004+
if (0 == rc) {
1005+
J9JFRThreadContextSwitchRate *jfrEvent = (J9JFRThreadContextSwitchRate *)reserveBuffer(currentThread, sizeof(J9JFRThreadContextSwitchRate));
1006+
if (NULL != jfrEvent) {
1007+
JFRState *jfrState = &currentThread->javaVM->jfrState;
1008+
int64_t currentTime = j9time_nano_time();
1009+
1010+
initializeEventFields(currentThread, (J9JFREvent *)jfrEvent, J9JFR_EVENT_TYPE_THREAD_CONTEXT_SWITCH_RATE);
1011+
1012+
if (-1 == jfrState->prevContextSwitchTimestamp) {
1013+
jfrEvent->switchRate = 0;
1014+
} else {
1015+
int64_t timeDelta = currentTime - jfrState->prevContextSwitchTimestamp;
1016+
jfrEvent->switchRate = ((double)(switches - jfrState->prevContextSwitches) / timeDelta) * 1e9;
1017+
}
1018+
jfrState->prevContextSwitches = switches;
1019+
jfrState->prevContextSwitchTimestamp = currentTime;
1020+
}
1021+
}
1022+
}
1023+
9911024
static int J9THREAD_PROC
9921025
jfrSamplingThreadProc(void *entryArg)
9931026
{
@@ -1006,11 +1039,12 @@ jfrSamplingThreadProc(void *entryArg)
10061039
internalAcquireVMAccess(currentThread);
10071040
jfrCPULoad(currentThread);
10081041
jfrClassLoadingStatistics(currentThread);
1009-
internalReleaseVMAccess(currentThread);
1010-
omrthread_monitor_enter(vm->jfrSamplerMutex);
10111042
if (0 == (count % 1000)) { // 10 seconds
10121043
J9SignalAsyncEvent(vm, NULL, vm->jfrThreadCPULoadAsyncKey);
1044+
jfrThreadContextSwitchRate(currentThread);
10131045
}
1046+
internalReleaseVMAccess(currentThread);
1047+
omrthread_monitor_enter(vm->jfrSamplerMutex);
10141048
}
10151049
count += 1;
10161050
omrthread_monitor_wait_timed(vm->jfrSamplerMutex, J9JFR_SAMPLING_RATE, 0);

0 commit comments

Comments
 (0)