Skip to content

Commit

Permalink
feat: add support for jdk.ObjectAllocationSample (#263)
Browse files Browse the repository at this point in the history
  • Loading branch information
yanglong1010 authored Mar 18, 2024
1 parent bf5f2c3 commit 0d17fa4
Show file tree
Hide file tree
Showing 14 changed files with 185 additions and 62 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -396,9 +396,10 @@ private void parseEventItem(IItem item) {

synchronized (this.context.getEvents()) {
this.context.addEvent(event);
if (event.getSettingFor() != null) {
RecordedEvent.SettingFor sf = event.getSettingFor();
this.context.putEventTypeId(sf.getEventType(), sf.getEventId());
if (event.getActiveSetting() != null) {
RecordedEvent.ActiveSetting activeSetting = event.getActiveSetting();
this.context.putEventTypeId(activeSetting.eventType(), activeSetting.eventId());
this.context.putActiveSetting(activeSetting, event);
}
}
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -31,7 +31,7 @@ public abstract class EventConstant {
public static String NATIVE_EXECUTION_SAMPLE = "jdk.NativeMethodSample";
public static String EXECUTE_VM_OPERATION = "jdk.ExecuteVMOperation";

public static String OBJECT_ALLOCATION_SAMPLE = "jdk.ObjectAllocationSample"; // TODO
public static String OBJECT_ALLOCATION_SAMPLE = "jdk.ObjectAllocationSample";
public static String OBJECT_ALLOCATION_IN_NEW_TLAB = "jdk.ObjectAllocationInNewTLAB";
public static String OBJECT_ALLOCATION_OUTSIDE_TLAB = "jdk.ObjectAllocationOutsideTLAB";

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -33,35 +33,37 @@ public AllocatedMemoryExtractor(JFRAnalysisContext context) {

@Override
void visitObjectAllocationInNewTLAB(RecordedEvent event) {
RecordedStackTrace stackTrace = event.getStackTrace();
if (stackTrace == null) {
if (this.useObjectAllocationSample) {
return;
}
this.visitTLABEvent(event, "tlabSize");
}

AllocationsExtractor.AllocTaskData allocThreadData = getThreadData(event.getThread());
if (allocThreadData.getSamples() == null) {
allocThreadData.setSamples(new HashMap<>());
@Override
void visitObjectAllocationOutsideTLAB(RecordedEvent event) {
if (this.useObjectAllocationSample) {
return;
}

long eventTotal = event.getLong("tlabSize");

allocThreadData.getSamples().compute(stackTrace, (k, temp) -> temp == null ? eventTotal : temp + eventTotal);
allocThreadData.allocatedMemory += eventTotal;
this.visitTLABEvent(event, "allocationSize");
}

@Override
void visitObjectAllocationOutsideTLAB(RecordedEvent event) {
void visitObjectAllocationSample(RecordedEvent event) {
this.visitTLABEvent(event, "weight");
}

void visitTLABEvent(RecordedEvent event, String fieldName) {
RecordedStackTrace stackTrace = event.getStackTrace();
if (stackTrace == null) {
return;
stackTrace = StackTraceUtil.DUMMY_STACK_TRACE;
}

AllocTaskData allocThreadData = getThreadData(event.getThread());
AllocationsExtractor.AllocTaskData allocThreadData = getThreadData(event.getThread());
if (allocThreadData.getSamples() == null) {
allocThreadData.setSamples(new HashMap<>());
}

long eventTotal = event.getLong("allocationSize");
long eventTotal = event.getLong(fieldName);

allocThreadData.getSamples().compute(stackTrace, (k, temp) -> temp == null ? eventTotal : temp + eventTotal);
allocThreadData.allocatedMemory += eventTotal;
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -26,12 +26,16 @@
import java.util.*;
import java.util.stream.Collectors;

import static org.eclipse.jifa.jfr.common.EventConstant.OBJECT_ALLOCATION_SAMPLE;

public class AllocationsExtractor extends Extractor {
protected boolean useObjectAllocationSample;

protected static final List<String> INTERESTED = Collections.unmodifiableList(new ArrayList<String>() {
protected static final List<String> INTERESTED = Collections.unmodifiableList(new ArrayList<>() {
{
add(EventConstant.OBJECT_ALLOCATION_IN_NEW_TLAB);
add(EventConstant.OBJECT_ALLOCATION_OUTSIDE_TLAB);
add(OBJECT_ALLOCATION_SAMPLE);
}
});

Expand All @@ -49,6 +53,11 @@ protected static class AllocTaskData extends TaskData {

public AllocationsExtractor(JFRAnalysisContext context) {
super(context, INTERESTED);
try {
this.useObjectAllocationSample = this.context.getActiveSettingBool(OBJECT_ALLOCATION_SAMPLE, "enabled");
} catch (Exception e) {
this.useObjectAllocationSample = false;
}
}

AllocTaskData getThreadData(RecordedThread thread) {
Expand All @@ -57,9 +66,29 @@ AllocTaskData getThreadData(RecordedThread thread) {

@Override
void visitObjectAllocationInNewTLAB(RecordedEvent event) {
if (useObjectAllocationSample) {
return;
}
visitEvent(event);
}

@Override
void visitObjectAllocationOutsideTLAB(RecordedEvent event) {
if (useObjectAllocationSample) {
return;
}
this.visitEvent(event);
}

@Override
void visitObjectAllocationSample(RecordedEvent event) {
this.visitEvent(event);
}

void visitEvent(RecordedEvent event) {
RecordedStackTrace stackTrace = event.getStackTrace();
if (stackTrace == null) {
return;
stackTrace = StackTraceUtil.DUMMY_STACK_TRACE;
}

AllocTaskData allocThreadData = getThreadData(event.getThread());
Expand All @@ -71,11 +100,6 @@ void visitObjectAllocationInNewTLAB(RecordedEvent event) {
allocThreadData.allocations += 1;
}

@Override
void visitObjectAllocationOutsideTLAB(RecordedEvent event) {
this.visitObjectAllocationInNewTLAB(event);
}

private List<TaskAllocations> buildThreadAllocations() {
List<TaskAllocations> taskAllocations = new ArrayList<>();
for (AllocTaskData data : this.data.values()) {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -42,7 +42,7 @@ void visitExecutionSample(RecordedEvent event) {

@Override
void visitActiveSetting(RecordedEvent event) {
if (this.context.isExecutionSampleEventTypeId(event.getSettingFor().getEventId())) {
if (this.context.isExecutionSampleEventTypeId(event.getActiveSetting().eventId())) {
if (EventConstant.WALL.equals(event.getString("name"))) {
this.isWallClockEvents = true;
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -79,7 +79,7 @@ private static class CpuTaskData extends TaskData {

private boolean isWallClockEvents = false;

private static final RecordedStackTrace DUMMY_STACK_TRACE = newDummyStackTrace("", "", "NO Frame");

private static final RecordedThread DUMMY_THREAD = new RecordedThread("Dummy Thread", -1L, -1L);
private static final RecordedThread GC_THREAD = new RecordedThread("GC Thread", -10L, -10L);

Expand Down Expand Up @@ -126,7 +126,7 @@ void visitGarbageCollection(RecordedEvent event) {

@Override
void visitActiveSetting(RecordedEvent event) {
if (event.getSettingFor().getEventId() == threadCPULoadEventId
if (event.getActiveSetting().eventId() == threadCPULoadEventId
&& EventConstant.PERIOD.equals(event.getString("name"))) {
updatePeriod(event.getValue("value"));
}
Expand All @@ -135,7 +135,7 @@ void visitActiveSetting(RecordedEvent event) {
this.isWallClockEvents = true;
}

if (this.context.isExecutionSampleEventTypeId(event.getSettingFor().getEventId())) {
if (this.context.isExecutionSampleEventTypeId(event.getActiveSetting().eventId())) {
if (EventConstant.WALL.equals(event.getString("name"))) {
this.isWallClockEvents = true;
} else if (EventConstant.INTERVAL.equals(event.getString("name"))) {
Expand Down Expand Up @@ -198,7 +198,7 @@ void visitThreadCPULoad(RecordedEvent event) {
void visitExecutionSample(RecordedEvent event) {
RecordedStackTrace stackTrace = event.getStackTrace();
if (stackTrace == null) {
stackTrace = DUMMY_STACK_TRACE;
stackTrace = StackTraceUtil.DUMMY_STACK_TRACE;
}

RecordedThread thread = event.getThread("eventThread");
Expand Down Expand Up @@ -269,7 +269,7 @@ private List<TaskCPUTime> buildThreadCPUTime() {
gc.setTask(context.getThread(GC_THREAD));
gc.setUser(gcTime);
Map<StackTrace, Long> gcSamples = new HashMap<>();
gcSamples.put(StackTraceUtil.build(newDummyStackTrace("", "JVM", "GC"), context.getSymbols()), 1L);
gcSamples.put(StackTraceUtil.build(StackTraceUtil.newDummyStackTrace("", "JVM", "GC"), context.getSymbols()), 1L);
gc.setSamples(gcSamples);
threadCPUTimes.add(gc);
}
Expand Down Expand Up @@ -299,22 +299,6 @@ public void fillResult(AnalysisResult result) {
result.setCpuTime(cpuResult);
}

private static RecordedStackTrace newDummyStackTrace(String packageName, String className, String methodName) {
RecordedStackTrace st = new RecordedStackTrace();
List<RecordedFrame> list = new ArrayList<>();
RecordedFrame f = new RecordedFrame();
RecordedMethod m = new RecordedMethod();
RecordedClass c = new RecordedClass();
c.setPackageName(packageName);
c.setName(className);
m.setType(c);
f.setMethod(m);
m.setName(methodName);
list.add(f);
st.setFrames(list);
return st;
}

private static long detectAsyncProfilerInterval() {
long interval = 0;
String intervalStr = System.getProperty("asyncProfilerCpuIntervalMs");
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -71,6 +71,10 @@ void visitObjectAllocationOutsideTLAB(RecordedEvent event) {
throw new UnsupportedOperationException();
}

void visitObjectAllocationSample(RecordedEvent event) {
throw new UnsupportedOperationException();
}

void visitFileRead(RecordedEvent event) {
throw new UnsupportedOperationException();
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -38,6 +38,7 @@ public abstract class Extractor extends EventVisitor {
put(EventConstant.EXECUTE_VM_OPERATION, EventVisitor::visitExecuteVMOperation);
put(EventConstant.OBJECT_ALLOCATION_IN_NEW_TLAB, EventVisitor::visitObjectAllocationInNewTLAB);
put(EventConstant.OBJECT_ALLOCATION_OUTSIDE_TLAB, EventVisitor::visitObjectAllocationOutsideTLAB);
put(EventConstant.OBJECT_ALLOCATION_SAMPLE, EventVisitor::visitObjectAllocationSample);

put(EventConstant.FILE_FORCE, EventVisitor::visitFileForce);
put(EventConstant.FILE_READ, EventVisitor::visitFileRead);
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -23,8 +23,11 @@

import java.util.*;

import static org.eclipse.jifa.jfr.common.EventConstant.OBJECT_ALLOCATION_SAMPLE;

public class JFRAnalysisContext {
private final Map<String, Long> eventTypeIds = new HashMap<>();
private final Map<RecordedEvent.ActiveSetting, String> activeSettings = new HashMap<>();
private final Map<Long, JavaThread> threads = new HashMap<>();
private final Map<String, Long> threadNameMap = new HashMap<>();
@Getter
Expand All @@ -51,13 +54,26 @@ public synchronized void putEventTypeId(String key, Long id) {
}
}

public synchronized void putActiveSetting(RecordedEvent.ActiveSetting activeSetting, RecordedEvent event) {
this.activeSettings.put(activeSetting, event.getString("value"));
}

public synchronized boolean getActiveSettingBool(String eventName, String settingName) {
Long eventId = this.getEventTypeId(OBJECT_ALLOCATION_SAMPLE);
RecordedEvent.ActiveSetting setting = new RecordedEvent.ActiveSetting(eventName, eventId, settingName);
String v = this.activeSettings.get(setting);
if (v != null) {
return Boolean.parseBoolean(v);
}
throw new RuntimeException("should not reach here");
}

public synchronized boolean isExecutionSampleEventTypeId(long id) {
return executionSampleEventTypeIds.contains(id);
}

public synchronized JavaThread getThread(RecordedThread thread) {
return threads.computeIfAbsent(thread.getJavaThreadId(), id -> {

JavaThread javaThread = new JavaThread();
javaThread.setId(id);
javaThread.setJavaId(thread.getJavaThreadId());
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -85,7 +85,7 @@ void visitActiveSetting(RecordedEvent event) {
this.isWallClockEvents = true;
}

if (event.getSettingFor().getEventId() == methodSampleEventId) {
if (event.getActiveSetting().eventId() == methodSampleEventId) {
if (EventConstant.WALL.equals(event.getString("name"))) {
this.isWallClockEvents = true;
this.interval = Long.parseLong(event.getString("value")) * 1000 * 1000;
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -30,6 +30,9 @@
import java.util.ArrayList;
import java.util.List;
import java.util.Map;
import java.util.Objects;

import static org.eclipse.jifa.jfr.common.EventConstant.ACTIVE_SETTING;

@Slf4j
public class RecordedEvent {
Expand All @@ -46,7 +49,7 @@ public class RecordedEvent {
@Getter
private EventType eventType;
@Getter
private SettingFor settingFor = null;
private ActiveSetting activeSetting = null;

public static RecordedEvent newInstance(IItem item, SymbolTable<SymbolBase> symbols) {
RecordedEvent event = new RecordedEvent(item);
Expand Down Expand Up @@ -80,9 +83,11 @@ private void init(SymbolTable<SymbolBase> symbols) {
// fix for JDK Mission Control lib
if ((itemTypeId.startsWith(EventConstant.EXECUTION_SAMPLE) && !itemTypeId.equals(EventConstant.EXECUTION_SAMPLE))) {
itemTypeId = EventConstant.EXECUTION_SAMPLE;
} else if (itemTypeId.startsWith(EventConstant.OBJECT_ALLOCATION_OUTSIDE_TLAB) && !itemTypeId.equals(EventConstant.OBJECT_ALLOCATION_OUTSIDE_TLAB)) {
} else if (itemTypeId.startsWith(EventConstant.OBJECT_ALLOCATION_OUTSIDE_TLAB)
&& !itemTypeId.equals(EventConstant.OBJECT_ALLOCATION_OUTSIDE_TLAB)) {
itemTypeId = EventConstant.OBJECT_ALLOCATION_OUTSIDE_TLAB;
} else if (itemTypeId.startsWith(EventConstant.OBJECT_ALLOCATION_IN_NEW_TLAB) && !itemTypeId.equals(EventConstant.OBJECT_ALLOCATION_IN_NEW_TLAB)) {
} else if (itemTypeId.startsWith(EventConstant.OBJECT_ALLOCATION_IN_NEW_TLAB)
&& !itemTypeId.equals(EventConstant.OBJECT_ALLOCATION_IN_NEW_TLAB)) {
itemTypeId = EventConstant.OBJECT_ALLOCATION_IN_NEW_TLAB;
}

Expand Down Expand Up @@ -139,15 +144,29 @@ private void init(SymbolTable<SymbolBase> symbols) {
stackTrace = st;
}

if ("jdk.ActiveSetting".equals(itemType.getIdentifier())) {
if (ACTIVE_SETTING.equals(itemType.getIdentifier())) {
String eventName = null;
long eventId = -1;
String settingName = null;
for (Map.Entry<IAccessorKey<?>, ? extends IDescribable> entry : itemType.getAccessorKeys().entrySet()) {
IMemberAccessor<?, IItem> accessor = itemType.getAccessor(entry.getKey());
if (entry.getKey().getIdentifier().equals("settingFor")) {
IMemberAccessor<?, IItem> accessor = itemType.getAccessor(entry.getKey());
LabeledIdentifier id = (LabeledIdentifier) accessor.getMember(item);
this.settingFor = new SettingFor(id.getInterfaceId(), id.getImplementationId());
eventName = id.getInterfaceId();
eventId = id.getImplementationId();
continue;
}
if (entry.getKey().getIdentifier().equals("name")) {
IMemberAccessor<?, IItem> accessor = itemType.getAccessor(entry.getKey());
settingName = (String) accessor.getMember(item);
}
if (eventName != null && settingName != null && eventId >= 0) {
break;
}
}
if (eventName != null && settingName != null && eventId >= 0) {
this.activeSetting = new ActiveSetting(eventName, eventId, settingName);
}
}
}

Expand Down Expand Up @@ -296,14 +315,16 @@ private static String formatPackage(IMCPackage mcPackage) {
return FormatToolkit.getPackage(mcPackage);
}

@Getter
public static class SettingFor {
private final String eventType;
private final long eventId;
public record ActiveSetting(String eventType, Long eventId, String settingName) {
@Override
public boolean equals(Object b) {
if (!(b instanceof ActiveSetting other)) {
return false;
}

SettingFor(String eventType, long eventId) {
this.eventId = eventId;
this.eventType = eventType;
return Objects.equals(eventType, other.eventType())
&& Objects.equals(eventId, other.eventId())
&& Objects.equals(settingName, other.settingName());
}
}
}
Loading

0 comments on commit 0d17fa4

Please sign in to comment.