Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

feat: add support for jdk.ObjectAllocationSample #263

Merged
merged 1 commit into from
Mar 18, 2024
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
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
Loading