Skip to content

Commit 462d7f8

Browse files
committed
Update JfrReader
1 parent 60b546d commit 462d7f8

File tree

2 files changed

+65
-13
lines changed

2 files changed

+65
-13
lines changed

spark-common/src/main/java/me/lucko/spark/common/sampler/async/jfr/Dictionary.java

Lines changed: 25 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -5,6 +5,8 @@
55

66
package me.lucko.spark.common.sampler.async.jfr;
77

8+
import java.util.Arrays;
9+
810
/**
911
* Fast and compact long->Object map.
1012
*/
@@ -16,26 +18,35 @@ public class Dictionary<T> {
1618
private int size;
1719

1820
public Dictionary() {
19-
this.keys = new long[INITIAL_CAPACITY];
20-
this.values = new Object[INITIAL_CAPACITY];
21+
this(INITIAL_CAPACITY);
22+
}
23+
24+
public Dictionary(int initialCapacity) {
25+
this.keys = new long[initialCapacity];
26+
this.values = new Object[initialCapacity];
2127
}
2228

2329
public void clear() {
24-
keys = new long[INITIAL_CAPACITY];
25-
values = new Object[INITIAL_CAPACITY];
30+
Arrays.fill(keys, 0);
31+
Arrays.fill(values, null);
2632
size = 0;
2733
}
2834

29-
// spark start
3035
public int size() {
31-
return this.size;
36+
return size;
3237
}
33-
// spark end
3438

35-
public void put(long key, T value) {
36-
if (key == 0) {
37-
throw new IllegalArgumentException("Zero key not allowed");
39+
// key[i]==0 is used to signal that the i-th position is unset.
40+
// Thus, we map key=key+1, so the user can still use key=0.
41+
private static long remapKey(long key) {
42+
if (key < 0) {
43+
throw new IllegalArgumentException("Negative keys not allowed");
3844
}
45+
return key + 1;
46+
}
47+
48+
public void put(long key, T value) {
49+
key = remapKey(key);
3950

4051
int mask = keys.length - 1;
4152
int i = hashCode(key) & mask;
@@ -56,6 +67,8 @@ public void put(long key, T value) {
5667

5768
@SuppressWarnings("unchecked")
5869
public T get(long key) {
70+
key = remapKey(key);
71+
5972
int mask = keys.length - 1;
6073
int i = hashCode(key) & mask;
6174
while (keys[i] != key && keys[i] != 0) {
@@ -68,7 +81,8 @@ public T get(long key) {
6881
public void forEach(Visitor<T> visitor) {
6982
for (int i = 0; i < keys.length; i++) {
7083
if (keys[i] != 0) {
71-
visitor.visit(keys[i], (T) values[i]);
84+
// Map key back, see remapKey
85+
visitor.visit(keys[i] - 1, (T) values[i]);
7286
}
7387
}
7488
}

spark-common/src/main/java/me/lucko/spark/common/sampler/async/jfr/JfrReader.java

Lines changed: 40 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -26,6 +26,7 @@
2626
/**
2727
* Parses JFR output produced by async-profiler.
2828
*/
29+
@SuppressWarnings("UnqualifiedFieldAccess")
2930
public class JfrReader implements Closeable {
3031
private static final int BUFFER_SIZE = 2 * 1024 * 1024;
3132
private static final int CHUNK_HEADER_SIZE = 68;
@@ -53,7 +54,7 @@ public class JfrReader implements Closeable {
5354

5455
public final Dictionary<JfrClass> types = new Dictionary<>();
5556
public final Map<String, JfrClass> typesByName = new HashMap<>();
56-
public final Map<Long, String> threads = new HashMap<>(); // spark - convert to map
57+
public final Dictionary<String> threads = new Dictionary<>();
5758
public final Dictionary<ClassRef> classes = new Dictionary<>();
5859
public final Dictionary<String> strings = new Dictionary<>();
5960
public final Dictionary<byte[]> symbols = new Dictionary<>();
@@ -75,6 +76,8 @@ public class JfrReader implements Closeable {
7576
private int monitorEnter;
7677
private int threadPark;
7778
private int activeSetting;
79+
private int malloc;
80+
private int free;
7881

7982
public JfrReader(Path path) throws IOException { // spark - Path instead of String
8083
this.ch = FileChannel.open(path, StandardOpenOption.READ); // spark - Path instead of String
@@ -118,6 +121,10 @@ public long durationNanos() {
118121
return endNanos - startNanos;
119122
}
120123

124+
public long chunkDurationNanos() {
125+
return chunkEndNanos - chunkStartNanos;
126+
}
127+
121128
public <E extends Event> void registerEvent(String name, Class<E> eventClass) {
122129
JfrClass type = typesByName.get(name);
123130
if (type != null) {
@@ -176,6 +183,10 @@ public <E extends Event> E readEvent(Class<E> cls) throws IOException {
176183
if (cls == null || cls == AllocationSample.class) return (E) readAllocationSample(true);
177184
} else if (type == allocationOutsideTLAB || type == allocationSample) {
178185
if (cls == null || cls == AllocationSample.class) return (E) readAllocationSample(false);
186+
} else if (type == malloc) {
187+
if (cls == null || cls == MallocEvent.class) return (E) readMallocEvent(true);
188+
} else if (type == free) {
189+
if (cls == null || cls == MallocEvent.class) return (E) readMallocEvent(false);
179190
} else if (type == liveObject) {
180191
if (cls == null || cls == LiveObject.class) return (E) readLiveObject();
181192
} else if (type == monitorEnter) {
@@ -223,6 +234,15 @@ private AllocationSample readAllocationSample(boolean tlab) {
223234
return new AllocationSample(time, tid, stackTraceId, classId, allocationSize, tlabSize);
224235
}
225236

237+
private MallocEvent readMallocEvent(boolean hasSize) {
238+
long time = getVarlong();
239+
int tid = getVarint();
240+
int stackTraceId = getVarint();
241+
long address = getVarlong();
242+
long size = hasSize ? getVarlong() : 0;
243+
return new MallocEvent(time, tid, stackTraceId, address, size);
244+
}
245+
226246
private LiveObject readLiveObject() {
227247
long time = getVarlong();
228248
int tid = getVarint();
@@ -409,7 +429,7 @@ private void readConstants(JfrClass type) {
409429
}
410430

411431
private void readThreads(int fieldCount) {
412-
int count = getVarint(); // spark - don't preallocate
432+
int count = threads.preallocate(getVarint());
413433
for (int i = 0; i < count; i++) {
414434
long id = getVarlong();
415435
String osName = getString();
@@ -543,6 +563,8 @@ private void cacheEventTypes() {
543563
monitorEnter = getTypeId("jdk.JavaMonitorEnter");
544564
threadPark = getTypeId("jdk.ThreadPark");
545565
activeSetting = getTypeId("jdk.ActiveSetting");
566+
malloc = getTypeId("profiler.Malloc");
567+
free = getTypeId("profiler.Free");
546568

547569
registerEvent("jdk.CPULoad", CPULoad.class);
548570
registerEvent("jdk.GCHeapSummary", GCHeapSummary.class);
@@ -966,6 +988,22 @@ public long value() {
966988
}
967989
}
968990

991+
static class MallocEvent extends Event {
992+
public final long address;
993+
public final long size;
994+
995+
public MallocEvent(long time, int tid, int stackTraceId, long address, long size) {
996+
super(time, tid, stackTraceId);
997+
this.address = address;
998+
this.size = size;
999+
}
1000+
1001+
@Override
1002+
public long value() {
1003+
return size;
1004+
}
1005+
}
1006+
9691007
static class ObjectCount extends Event {
9701008
public final int gcId;
9711009
public final int classId;

0 commit comments

Comments
 (0)