Bug 1077469 - Build flame graph for memory allocations view, r=jsantell

This commit is contained in:
Victor Porof 2015-02-02 21:29:46 -05:00
parent 4e268a4985
commit 6e9c7248fa
5 changed files with 54 additions and 15 deletions

View File

@ -76,6 +76,11 @@ exports.RecordingUtils.offsetAndScaleTimestamps = function(timestamps, timeOffse
} }
} }
/**
* Cache used in `RecordingUtils.getSamplesFromAllocations`.
*/
let gSamplesFromAllocationCache = new WeakMap();
/** /**
* Converts allocation data from the memory actor to something that follows * Converts allocation data from the memory actor to something that follows
* the same structure as the samples data received from the profiler. * the same structure as the samples data received from the profiler.
@ -88,6 +93,11 @@ exports.RecordingUtils.offsetAndScaleTimestamps = function(timestamps, timeOffse
* The samples data. * The samples data.
*/ */
exports.RecordingUtils.getSamplesFromAllocations = function(allocations) { exports.RecordingUtils.getSamplesFromAllocations = function(allocations) {
let cached = gSamplesFromAllocationCache.get(allocations);
if (cached) {
return cached;
}
let { sites, timestamps, frames, counts } = allocations; let { sites, timestamps, frames, counts } = allocations;
let samples = []; let samples = [];
@ -117,5 +127,6 @@ exports.RecordingUtils.getSamplesFromAllocations = function(allocations) {
sample.frames.reverse(); sample.frames.reverse();
} }
gSamplesFromAllocationCache.set(allocations, samples);
return samples; return samples;
} }

View File

@ -15,8 +15,6 @@ let MemoryCallTreeView = Heritage.extend(DetailsSubview, {
initialize: function () { initialize: function () {
DetailsSubview.initialize.call(this); DetailsSubview.initialize.call(this);
this._cache = new WeakMap();
this._onPrefChanged = this._onPrefChanged.bind(this); this._onPrefChanged = this._onPrefChanged.bind(this);
this._onLink = this._onLink.bind(this); this._onLink = this._onLink.bind(this);
@ -63,14 +61,7 @@ let MemoryCallTreeView = Heritage.extend(DetailsSubview, {
* populate the call tree. * populate the call tree.
*/ */
_prepareCallTree: function (allocations, { startTime, endTime }, options) { _prepareCallTree: function (allocations, { startTime, endTime }, options) {
let cached = this._cache.get(allocations); let samples = RecordingUtils.getSamplesFromAllocations(allocations);
if (cached) {
var samples = cached;
} else {
var samples = RecordingUtils.getSamplesFromAllocations(allocations);
this._cache.set(allocations, samples);
}
let contentOnly = !Prefs.showPlatformData; let contentOnly = !Prefs.showPlatformData;
let invertTree = PerformanceController.getPref("invert-call-tree"); let invertTree = PerformanceController.getPref("invert-call-tree");

View File

@ -6,8 +6,6 @@
/** /**
* FlameGraph view containing a pyramid-like visualization of memory allocation * FlameGraph view containing a pyramid-like visualization of memory allocation
* sites, controlled by DetailsView. * sites, controlled by DetailsView.
*
* TODO: bug 1077469
*/ */
let MemoryFlameGraphView = Heritage.extend(DetailsSubview, { let MemoryFlameGraphView = Heritage.extend(DetailsSubview, {
/** /**
@ -15,6 +13,14 @@ let MemoryFlameGraphView = Heritage.extend(DetailsSubview, {
*/ */
initialize: Task.async(function* () { initialize: Task.async(function* () {
DetailsSubview.initialize.call(this); DetailsSubview.initialize.call(this);
this.graph = new FlameGraph($("#memory-flamegraph-view"));
this.graph.timelineTickUnits = L10N.getStr("graphs.ms");
yield this.graph.ready();
this._onRangeChangeInGraph = this._onRangeChangeInGraph.bind(this);
this.graph.on("selecting", this._onRangeChangeInGraph);
}), }),
/** /**
@ -22,6 +28,8 @@ let MemoryFlameGraphView = Heritage.extend(DetailsSubview, {
*/ */
destroy: function () { destroy: function () {
DetailsSubview.destroy.call(this); DetailsSubview.destroy.call(this);
this.graph.off("selecting", this._onRangeChangeInGraph);
}, },
/** /**
@ -31,6 +39,35 @@ let MemoryFlameGraphView = Heritage.extend(DetailsSubview, {
* The { startTime, endTime }, in milliseconds. * The { startTime, endTime }, in milliseconds.
*/ */
render: function (interval={}) { render: function (interval={}) {
let recording = PerformanceController.getCurrentRecording();
let duration = recording.getDuration();
let allocations = recording.getAllocations();
let samples = RecordingUtils.getSamplesFromAllocations(allocations);
let data = FlameGraphUtils.createFlameGraphDataFromSamples(samples, {
flattenRecursion: Prefs.flattenTreeRecursion,
showIdleBlocks: Prefs.showIdleBlocks && L10N.getStr("table.idle")
});
this.graph.setData({ data,
bounds: {
startTime: 0,
endTime: duration
},
visible: {
startTime: interval.startTime || 0,
endTime: interval.endTime || duration
}
});
this.emit(EVENTS.MEMORY_FLAMEGRAPH_RENDERED); this.emit(EVENTS.MEMORY_FLAMEGRAPH_RENDERED);
},
/**
* Fired when a range is selected or cleared in the FlameGraph.
*/
_onRangeChangeInGraph: function () {
let interval = this.graph.getViewRange();
OverviewView.setTimeInterval(interval, { stopPropagation: true });
} }
}); });

View File

@ -49,9 +49,9 @@ function testGraph(graph) {
scroll(graph, 10000, HORIZONTAL_AXIS, 1); scroll(graph, 10000, HORIZONTAL_AXIS, 1);
is(graph.getViewRange().startTime, 140, is(Math.round(graph.getViewRange().startTime), 150,
"The selection start boundary is correct on HiDPI (2)."); "The selection start boundary is correct on HiDPI (2).");
is(graph.getViewRange().endTime, 150, is(Math.round(graph.getViewRange().endTime), 150,
"The selection end boundary is correct on HiDPI (2)."); "The selection end boundary is correct on HiDPI (2).");
is(graph.getOuterBounds().startTime, 0, is(graph.getOuterBounds().startTime, 0,

View File

@ -24,7 +24,7 @@ const GRAPH_RESIZE_EVENTS_DRAIN = 100; // ms
const GRAPH_WHEEL_ZOOM_SENSITIVITY = 0.00035; const GRAPH_WHEEL_ZOOM_SENSITIVITY = 0.00035;
const GRAPH_WHEEL_SCROLL_SENSITIVITY = 0.5; const GRAPH_WHEEL_SCROLL_SENSITIVITY = 0.5;
const GRAPH_MIN_SELECTION_WIDTH = 20; // ms const GRAPH_MIN_SELECTION_WIDTH = 0.001; // ms
const TIMELINE_TICKS_MULTIPLE = 5; // ms const TIMELINE_TICKS_MULTIPLE = 5; // ms
const TIMELINE_TICKS_SPACING_MIN = 75; // px const TIMELINE_TICKS_SPACING_MIN = 75; // px