Skip to content

Commit

Permalink
Change int -> data map to ordinary array list.
Browse files Browse the repository at this point in the history
  • Loading branch information
jchalou committed Apr 8, 2024
1 parent 5d86317 commit 8efd0f3
Show file tree
Hide file tree
Showing 7 changed files with 69 additions and 63 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -127,12 +127,12 @@ public void start() {
@Override
public Params stop() {
long time = System.currentTimeMillis();
Map<Integer, CPUSamplerData> data;
List<CPUSamplerData> data;
long period;
synchronized (sampler) {
sampler.setCollecting(false);
sampler.setGatherSelfHitTimes(oldGatherSelfHitTimes);
data = sampler.getIndexedData();
data = sampler.getDataList();
sampler.clearData();
period = sampler.getPeriod();
}
Expand All @@ -141,18 +141,18 @@ public Params stop() {
return profile;
}

private static Collection<ProfilerNode<CPUSampler.Payload>> getRootNodes(Map<Integer, CPUSamplerData> data) {
private static Collection<ProfilerNode<CPUSampler.Payload>> getRootNodes(List<CPUSamplerData> data) {
Collection<ProfilerNode<CPUSampler.Payload>> retVal = new ArrayList<>();
for (CPUSamplerData samplerData : data.values()) {
for (CPUSamplerData samplerData : data) {
for (Collection<ProfilerNode<CPUSampler.Payload>> profilerNodes : samplerData.getThreadData().values()) {
retVal.addAll(profilerNodes);
}
}
return retVal;
}

private static long getSampleCount(Map<Integer, CPUSamplerData> data) {
return data.values().stream().map(CPUSamplerData::getSamples).reduce(0L, Long::sum);
private static long getSampleCount(List<CPUSamplerData> data) {
return data.stream().map(CPUSamplerData::getSamples).reduce(0L, Long::sum);
}

@Override
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -86,7 +86,7 @@ protected void initializeContext(LanguageContext c) throws Exception {
context.initialize(ProxyLanguage.ID);
sampler.setCollecting(false);

Map<Integer, CPUSamplerData> data = sampler.getIndexedData();
List<CPUSamplerData> data = sampler.getDataList();
assertEquals(1, data.size());

assertEquals(0, searchInitializeContext(data).size());
Expand All @@ -112,15 +112,15 @@ protected void initializeContext(LanguageContext c) throws Exception {
context.initialize(ProxyLanguage.ID);
sampler.setCollecting(false);

Map<Integer, CPUSamplerData> data = sampler.getIndexedData();
List<CPUSamplerData> data = sampler.getDataList();
assertEquals(1, data.size());

assertEquals(0, searchInitializeContext(data).size());
}

private static List<ProfilerNode<Payload>> searchInitializeContext(Map<Integer, CPUSamplerData> data) {
private static List<ProfilerNode<Payload>> searchInitializeContext(List<CPUSamplerData> data) {
List<ProfilerNode<Payload>> found = new ArrayList<>();
for (CPUSamplerData d : data.values()) {
for (CPUSamplerData d : data) {
Map<Thread, Collection<ProfilerNode<Payload>>> threadData = d.getThreadData();
assertEquals(threadData.toString(), 1, threadData.size());

Expand All @@ -145,17 +145,17 @@ private static void searchNodes(List<ProfilerNode<CPUSampler.Payload>> results,
public void testCollectingAndHasData() {

sampler.setCollecting(true);
Map<Integer, CPUSamplerData> before = sampler.getIndexedData();
Assert.assertEquals(0, before.values().iterator().next().getSamples());
List<CPUSamplerData> before = sampler.getDataList();
Assert.assertEquals(0, before.iterator().next().getSamples());
Assert.assertTrue(sampler.isCollecting());
Assert.assertFalse(sampler.hasData());

for (int i = 0; i < executionCount; i++) {
eval(defaultSourceForSampling);
}

Map<Integer, CPUSamplerData> after = sampler.getIndexedData();
Assert.assertNotEquals(0, after.values().iterator().next().getSamples());
List<CPUSamplerData> after = sampler.getDataList();
Assert.assertNotEquals(0, after.iterator().next().getSamples());
Assert.assertTrue(sampler.isCollecting());
Assert.assertTrue(sampler.hasData());

Expand All @@ -165,9 +165,9 @@ public void testCollectingAndHasData() {
Assert.assertTrue(sampler.hasData());

sampler.clearData();
Map<Integer, CPUSamplerData> cleared = sampler.getIndexedData();
List<CPUSamplerData> cleared = sampler.getDataList();
Assert.assertFalse(sampler.isCollecting());
Assert.assertEquals(0, cleared.values().iterator().next().getSamples());
Assert.assertEquals(0, cleared.iterator().next().getSamples());

Assert.assertFalse(sampler.hasData());
}
Expand Down Expand Up @@ -220,9 +220,9 @@ public void testCorrectRootStructure() {
}

private Collection<ProfilerNode<Payload>> getProfilerNodes() {
Map<Integer, CPUSamplerData> data = sampler.getIndexedData();
List<CPUSamplerData> data = sampler.getDataList();
Assert.assertEquals(1, data.size());
Map<Thread, Collection<ProfilerNode<Payload>>> threadData = data.values().iterator().next().getThreadData();
Map<Thread, Collection<ProfilerNode<Payload>>> threadData = data.iterator().next().getThreadData();
Assert.assertEquals(1, threadData.size());
Collection<ProfilerNode<Payload>> children = threadData.values().iterator().next();
return children;
Expand Down Expand Up @@ -337,16 +337,16 @@ public void testTiers() {
Assume.assumeFalse(Truffle.getRuntime().getClass().toString().contains("Default"));
Context.Builder builder = Context.newBuilder().option("engine.FirstTierCompilationThreshold", Integer.toString(FIRST_TIER_THRESHOLD)).option("engine.LastTierCompilationThreshold",
Integer.toString(2 * FIRST_TIER_THRESHOLD)).option("engine.BackgroundCompilation", "false");
Map<Integer, CPUSamplerData> data;
List<CPUSamplerData> data;
try (Context c = builder.build()) {
CPUSampler cpuSampler = CPUSampler.find(c.getEngine());
cpuSampler.setCollecting(true);
for (int i = 0; i < 3 * FIRST_TIER_THRESHOLD; i++) {
c.eval(defaultSourceForSampling);
}
data = cpuSampler.getIndexedData();
data = cpuSampler.getDataList();
}
CPUSamplerData samplerData = data.values().iterator().next();
CPUSamplerData samplerData = data.iterator().next();
Collection<ProfilerNode<CPUSampler.Payload>> profilerNodes = samplerData.getThreadData().values().iterator().next();
ProfilerNode<CPUSampler.Payload> root = profilerNodes.iterator().next();
for (ProfilerNode<CPUSampler.Payload> child : root.getChildren()) {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -363,8 +363,8 @@ public void testSamplerJson() {
final long sampleCount;
final boolean gatherSelfHitTimes;
synchronized (sampler) {
Map<Integer, CPUSamplerData> data = sampler.getIndexedData();
CPUSamplerData samplerData = data.values().iterator().next();
List<CPUSamplerData> data = sampler.getDataList();
CPUSamplerData samplerData = data.iterator().next();
threadToNodesMap = samplerData.getThreadData();
period = sampler.getPeriod();
sampleCount = samplerData.getSamples();
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -32,10 +32,10 @@
import java.util.HashMap;
import java.util.LinkedHashMap;
import java.util.List;
import java.util.ListIterator;
import java.util.Locale;
import java.util.LongSummaryStatistics;
import java.util.Map;
import java.util.Map.Entry;
import java.util.WeakHashMap;
import java.util.concurrent.ArrayBlockingQueue;
import java.util.concurrent.ExecutorService;
Expand Down Expand Up @@ -103,9 +103,9 @@ public CPUSampler create(Env env) {

private final Env env;

private int contextIndex;
private final Map<TruffleContext, Integer> activeContexts = Collections.synchronizedMap(new WeakHashMap<>());
private final Map<Integer, MutableSamplerData> samplerData = Collections.synchronizedMap(new LinkedHashMap<>());
private int nextContextIndex;
private final Map<TruffleContext, Integer> activeContexts = new WeakHashMap<>();
private final List<MutableSamplerData> samplerData = new ArrayList<>();
private volatile boolean closed;
private volatile boolean collecting;
private long period = 10;
Expand Down Expand Up @@ -139,9 +139,9 @@ public CPUSampler create(Env env) {
@Override
public void onContextCreated(TruffleContext context) {
synchronized (CPUSampler.this) {
contextIndex++;
int contextIndex = nextContextIndex++;
activeContexts.put(context, contextIndex);
samplerData.put(contextIndex, new MutableSamplerData());
samplerData.add(new MutableSamplerData(contextIndex));
}
}

Expand Down Expand Up @@ -337,7 +337,7 @@ public boolean hasStackOverflowed() {
* @return a map from {@link TruffleContext} to {@link CPUSamplerData}.
* @since 21.3.0
*
* @deprecated Contexts are no longer stored. Use {@link #getIndexedData()} to get per-context
* @deprecated Contexts are no longer stored. Use {@link #getDataList()} to get per-context
* sampler data.
*/
@Deprecated
Expand All @@ -348,34 +348,31 @@ public Map<TruffleContext, CPUSamplerData> getData() {

/**
* Get per-context profiling data. Context objects are not stored, the profiling data is an
* unmodifiable map that maps context indices to {@link CPUSamplerData}. It is collected based
* on the configuration of the {@link CPUSampler} (e.g. {@link #setFilter(SourceSectionFilter)},
* unmodifiable list of {@link CPUSamplerData}. It is collected based on the configuration of
* the {@link CPUSampler} (e.g. {@link #setFilter(SourceSectionFilter)},
* {@link #setPeriod(long)}, etc.) and collecting can be controlled by the
* {@link #setCollecting(boolean)}. The collected data can be cleared from the cpusampler using
* {@link #clearData()}
*
* @return a map from context indices to {@link CPUSamplerData}.
* @return a list of {@link CPUSamplerData} where each element corresponds to one context.
* @since 24.1.0
*/
public synchronized Map<Integer, CPUSamplerData> getIndexedData() {
public synchronized List<CPUSamplerData> getDataList() {
if (samplerData.isEmpty()) {
return Collections.emptyMap();
return Collections.emptyList();
}
Map<Integer, CPUSamplerData> contextToData = new HashMap<>();
for (Entry<Integer, MutableSamplerData> contextEntry : this.samplerData.entrySet()) {
List<CPUSamplerData> dataList = new ArrayList<>();
for (MutableSamplerData mutableSamplerData : this.samplerData) {
Map<Thread, Collection<ProfilerNode<Payload>>> threads = new HashMap<>();
final MutableSamplerData mutableSamplerData = contextEntry.getValue();
for (Map.Entry<Thread, ProfilerNode<Payload>> threadEntry : mutableSamplerData.threadData.entrySet()) {
ProfilerNode<Payload> copy = new ProfilerNode<>();
copy.deepCopyChildrenFrom(threadEntry.getValue(), COPY_PAYLOAD);
threads.put(threadEntry.getKey(), copy.getChildren());
}
int localContextIndex = contextEntry.getKey();
contextToData.put(localContextIndex,
new CPUSamplerData(localContextIndex, threads, mutableSamplerData.biasStatistic, mutableSamplerData.durationStatistic, mutableSamplerData.samplesTaken.get(), period,
mutableSamplerData.missedSamples.get()));
dataList.add(new CPUSamplerData(mutableSamplerData.index, threads, mutableSamplerData.biasStatistic, mutableSamplerData.durationStatistic, mutableSamplerData.samplesTaken.get(), period,
mutableSamplerData.missedSamples.get()));
}
return Collections.unmodifiableMap(contextToData);
return Collections.unmodifiableList(dataList);
}

/**
Expand All @@ -384,8 +381,8 @@ public synchronized Map<Integer, CPUSamplerData> getIndexedData() {
* @since 0.30
*/
public synchronized void clearData() {
for (Map.Entry<Integer, MutableSamplerData> dataEntry : samplerData.entrySet()) {
dataEntry.setValue(new MutableSamplerData());
for (ListIterator<MutableSamplerData> dataIterator = samplerData.listIterator(); dataIterator.hasNext();) {
dataIterator.set(new MutableSamplerData(dataIterator.next().index));
}
}

Expand All @@ -394,7 +391,7 @@ public synchronized void clearData() {
* @since 0.30
*/
public synchronized boolean hasData() {
for (MutableSamplerData mutableSamplerData : samplerData.values()) {
for (MutableSamplerData mutableSamplerData : samplerData) {
if (mutableSamplerData.samplesTaken.get() > 0) {
return true;
}
Expand Down Expand Up @@ -787,7 +784,11 @@ public void run() {
if (context.isClosed()) {
continue;
}
List<StackSample> samples = safepointStackSampler.sample(env, Collections.singletonMap(context, samplerData.get(activeContexts.get(context))), !sampleContextInitialization, period,
MutableSamplerData data;
synchronized (CPUSampler.this) {
data = samplerData.get(activeContexts.get(context));
}
List<StackSample> samples = safepointStackSampler.sample(env, Collections.singletonMap(context, data), !sampleContextInitialization, period,
TimeUnit.MILLISECONDS);
resultsToProcess.add(new SamplingResult(samples, context, taskStartTime));
}
Expand All @@ -796,11 +797,16 @@ public void run() {
}

static class MutableSamplerData {
final int index;
final Map<Thread, ProfilerNode<Payload>> threadData = new HashMap<>();
final AtomicLong samplesTaken = new AtomicLong(0);
final LongSummaryStatistics biasStatistic = new LongSummaryStatistics(); // nanoseconds
final LongSummaryStatistics durationStatistic = new LongSummaryStatistics(); // nanoseconds
final AtomicLong missedSamples = new AtomicLong(0);

public MutableSamplerData(int index) {
this.index = index;
}
}

private static String format(String format, Object... args) {
Expand All @@ -824,7 +830,7 @@ public void example() {
sampler.close();
// Read information about the roots of the tree per thread.
for (Collection<ProfilerNode<CPUSampler.Payload>> nodes
: sampler.getIndexedData().values().iterator().next().threadData.values()) {
: sampler.getDataList().iterator().next().threadData.values()) {
for (ProfilerNode<CPUSampler.Payload> node : nodes) {
final String rootName = node.getRootName();
final int selfHitCount = node.getPayload().getSelfHitCount();
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -35,7 +35,7 @@
/**
* Execution profile of a particular context.
*
* @see CPUSampler#getIndexedData()
* @see CPUSampler#getDataList()
* @since 21.3.0
*/
public final class CPUSamplerData {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -222,7 +222,7 @@ public int[] apply(String s) {

static void handleOutput(TruffleInstrument.Env env, CPUSampler sampler, String absoluteOutputPath) {
PrintStream out = chooseOutputStream(env, absoluteOutputPath);
Map<Integer, CPUSamplerData> data = sampler.getIndexedData();
List<CPUSamplerData> data = sampler.getDataList();
OptionValues options = env.getOptions();
switch (chooseOutput(options)) {
case HISTOGRAM:
Expand Down Expand Up @@ -275,15 +275,15 @@ private static Output chooseOutput(OptionValues options) {
return OUTPUT.getDefaultValue();
}

private static void printSamplingCallTree(PrintStream out, OptionValues options, Map<Integer, CPUSamplerData> data) {
for (Map.Entry<Integer, CPUSamplerData> entry : data.entrySet()) {
new SamplingCallTree(entry.getValue(), options).print(out);
private static void printSamplingCallTree(PrintStream out, OptionValues options, List<CPUSamplerData> data) {
for (CPUSamplerData entry : data) {
new SamplingCallTree(entry, options).print(out);
}
}

private static void printSamplingHistogram(PrintStream out, OptionValues options, Map<Integer, CPUSamplerData> data) {
for (Map.Entry<Integer, CPUSamplerData> entry : data.entrySet()) {
new SamplingHistogram(entry.getValue(), options).print(out);
private static void printSamplingHistogram(PrintStream out, OptionValues options, List<CPUSamplerData> data) {
for (CPUSamplerData entry : data) {
new SamplingHistogram(entry, options).print(out);
}
}

Expand All @@ -306,7 +306,7 @@ private static void printWarnings(CPUSampler sampler, PrintStream out) {
}

private static boolean sampleDurationTooLong(CPUSampler sampler) {
for (CPUSamplerData value : sampler.getIndexedData().values()) {
for (CPUSamplerData value : sampler.getDataList()) {
if (value.getSampleDuration().getAverage() > MAX_OVERHEAD_WARNING_THRESHOLD * sampler.getPeriod() * MILLIS_TO_NANOS) {
return true;
}
Expand All @@ -318,13 +318,13 @@ private static void printDiv(PrintStream out) {
out.println("-------------------------------------------------------------------------------- ");
}

private static void printSamplingJson(PrintStream out, OptionValues options, Map<Integer, CPUSamplerData> data) {
private static void printSamplingJson(PrintStream out, OptionValues options, List<CPUSamplerData> data) {
boolean gatheredHitTimes = options.get(GATHER_HIT_TIMES);
JSONObject output = new JSONObject();
output.put("tool", CPUSamplerInstrument.ID);
output.put("version", CPUSamplerInstrument.VERSION);
JSONArray contexts = new JSONArray();
for (CPUSamplerData samplerData : data.values()) {
for (CPUSamplerData samplerData : data) {
contexts.put(perContextData(samplerData, gatheredHitTimes));
}
output.put("contexts", contexts);
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -49,7 +49,7 @@

final class SVGSamplerOutput {

public static void printSamplingFlameGraph(PrintStream out, Map<Integer, CPUSamplerData> data) {
public static void printSamplingFlameGraph(PrintStream out, List<CPUSamplerData> data) {
GraphOwner graph = new GraphOwner(new StringBuilder(), data);

graph.addComponent(new SVGFlameGraph(graph));
Expand Down Expand Up @@ -214,7 +214,7 @@ private enum GraphColorMap {
private static class GraphOwner implements SVGComponent {

private final SVGSamplerOutput svg;
private final Map<Integer, CPUSamplerData> data;
private final List<CPUSamplerData> data;
private ArrayList<SVGComponent> components;
private Random random = new Random();
private Map<GraphColorMap, String> languageColors;
Expand All @@ -232,7 +232,7 @@ private static class GraphOwner implements SVGComponent {
public final JSONArray sampleJsonKeys = new JSONArray();
public final JSONArray sampleData = new JSONArray();

GraphOwner(StringBuilder output, Map<Integer, CPUSamplerData> data) {
GraphOwner(StringBuilder output, List<CPUSamplerData> data) {
svg = new SVGSamplerOutput(output);
this.data = data;
components = new ArrayList<>();
Expand Down Expand Up @@ -328,7 +328,7 @@ private void buildSampleData() {
root.put("l", GraphColorMap.GRAY.ordinal());
long totalSamples = 0;
JSONArray children = new JSONArray();
for (CPUSamplerData value : data.values()) {
for (CPUSamplerData value : data) {
for (Map.Entry<Thread, Collection<ProfilerNode<CPUSampler.Payload>>> node : value.getThreadData().entrySet()) {
Thread thread = node.getKey();
// Output the thread node itself...
Expand Down

0 comments on commit 8efd0f3

Please sign in to comment.