package com.jetbrains.actionscript.profiler.calltree;
import com.intellij.openapi.util.Pair;
import com.jetbrains.actionscript.profiler.sampler.FrameInfo;
import gnu.trove.THashMap;
import gnu.trove.THashSet;
import java.util.List;
import java.util.Map;
class TimeMapBuilder {
private TimeMapBuilder() {
}
/*
* @return pair <cumulative time map, self time map>
*/
static Pair<Map<FrameInfo, Long>, Map<FrameInfo, Long>> buildTimeMaps(CallTreeNode root, List<CallTreeNode> calls) {
Map<FrameInfo, Long> countMap = new THashMap<>();
Map<FrameInfo, Long> selfCountMap = new THashMap<>();
THashSet<CallTreeNode> trackedCalls = new THashSet<>(calls);
for (CallTreeNode node : root.getChildren()) {
fillTimeMaps(node, countMap, selfCountMap, trackedCalls.contains(node), trackedCalls);
}
return Pair.create(countMap, selfCountMap);
}
private static void fillTimeMaps(CallTreeNode node,
Map<FrameInfo, Long> countMap,
Map<FrameInfo, Long> selfCountMap,
boolean tracking,
THashSet<CallTreeNode> trackedCalls) {
if (tracking) {
updateSelfTime(node, selfCountMap);
}
//save value before subcalls
Long countBefore = countMap.get(node.getFrameInfo());
if (countBefore == null) {
countBefore = 0L;
}
for (CallTreeNode child : node.getChildren()) {
fillTimeMaps(child, countMap, selfCountMap, tracking || trackedCalls.contains(child), trackedCalls);
}
if (tracking) {
//rewrite values that were added in subcalls.
//cause of that we get value only of the nearest node to the root
countMap.put(node.getFrameInfo(), countBefore + node.getCumulativeTiming());
}
}
private static void updateSelfTime(CallTreeNode node, Map<FrameInfo, Long> selfCountMap) {
long currentSelfTime = node.getCumulativeTiming() - node.calcSelfTiming();
Long selfTime = selfCountMap.get(node.getFrameInfo());
if (selfTime == null) {
selfTime = 0L;
}
selfCountMap.put(node.getFrameInfo(), selfTime + currentSelfTime);
}
}