summaryrefslogtreecommitdiffstats
path: root/tools/deep_memory_profiler
diff options
context:
space:
mode:
authorjunjianx@chromium.org <junjianx@chromium.org@0039d316-1c4b-4281-b951-d872f2087c98>2013-08-14 02:30:36 +0000
committerjunjianx@chromium.org <junjianx@chromium.org@0039d316-1c4b-4281-b951-d872f2087c98>2013-08-14 02:30:36 +0000
commitfeceb564cfd997b9a0fd69803f7d01d6ed41053f (patch)
tree3414a7f322dd2c6ea5acc230a559e9ed9639d47b /tools/deep_memory_profiler
parent5e91599a896a0b82d37a39ab888a4203421cf2a6 (diff)
downloadchromium_src-feceb564cfd997b9a0fd69803f7d01d6ed41053f.zip
chromium_src-feceb564cfd997b9a0fd69803f7d01d6ed41053f.tar.gz
chromium_src-feceb564cfd997b9a0fd69803f7d01d6ed41053f.tar.bz2
Initial version of graph visualizer for dmprof
BUG=259206 NOTRY=True Review URL: https://chromiumcodereview.appspot.com/22440003 git-svn-id: svn://svn.chromium.org/chrome/trunk/src@217450 0039d316-1c4b-4281-b951-d872f2087c98
Diffstat (limited to 'tools/deep_memory_profiler')
-rw-r--r--tools/deep_memory_profiler/visualizer/main.css9
-rw-r--r--tools/deep_memory_profiler/visualizer/main.html17
-rw-r--r--tools/deep_memory_profiler/visualizer/main.js160
3 files changed, 186 insertions, 0 deletions
diff --git a/tools/deep_memory_profiler/visualizer/main.css b/tools/deep_memory_profiler/visualizer/main.css
new file mode 100644
index 0000000..5d9ed53
--- /dev/null
+++ b/tools/deep_memory_profiler/visualizer/main.css
@@ -0,0 +1,9 @@
+/* Copyright 2013 The Chromium Authors. All rights reserved.
+ * Use of this source code is governed by a BSD-style license that can be
+ * found in the LICENSE file. */
+
+.plot-container {
+ width: 1240px;
+ height: 720px;
+ margin: 30px auto 30px auto;
+} \ No newline at end of file
diff --git a/tools/deep_memory_profiler/visualizer/main.html b/tools/deep_memory_profiler/visualizer/main.html
new file mode 100644
index 0000000..fdd7874
--- /dev/null
+++ b/tools/deep_memory_profiler/visualizer/main.html
@@ -0,0 +1,17 @@
+<!DOCTYPE html>
+<!--
+Copyright 2013 The Chromium Authors. All rights reserved.
+Use of this source code is governed by a BSD-style license that can be
+found in the LICENSE file.
+-->
+<meta charset="utf-8">
+<link rel="stylesheet" href="main.css">
+<script src="../../../third_party/flot/jquery.min.js"></script>
+<script src="../../../third_party/flot/jquery.flot.min.js"></script>
+<script src="../../../third_party/flot/jquery.flot.stack.min.js"></script>
+<script src="main.js"></script>
+
+<body>
+ <h2>Deep Memory Profiler Visulaizer</h2>
+ <div id="plot" class="plot-container"></div>
+</body>
diff --git a/tools/deep_memory_profiler/visualizer/main.js b/tools/deep_memory_profiler/visualizer/main.js
new file mode 100644
index 0000000..8c4dff8
--- /dev/null
+++ b/tools/deep_memory_profiler/visualizer/main.js
@@ -0,0 +1,160 @@
+// Copyright 2013 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+/**
+ * This class provides data access interface for dump file profiler
+ * @constructor
+ */
+var Profiler = function(jsonData) {
+ this._jsonData = jsonData;
+};
+
+/**
+ * Get units of a snapshot in a world.
+ * Exception will be thrown when no world of given name exists.
+ * @param {string} worldName
+ * @param {number} snapshotIndex
+ * @return {Object.<string, number>}
+ */
+Profiler.prototype.getUnits = function(worldName, snapshotIndex) {
+ var snapshot = this._jsonData.snapshots[snapshotIndex];
+ if (!snapshot.worlds[worldName])
+ throw 'no world ' + worldName + ' in snapshot ' + index;
+
+ // Return units.
+ var world = snapshot.worlds[worldName];
+ var units = {};
+ for (var unitName in world.units)
+ units[unitName] = world.units[unitName][0];
+ return units;
+};
+
+/**
+ * Get first-level breakdowns of a snapshot in a world.
+ * Exception will be thrown when no world of given name exists.
+ * @param {string} worldName
+ * @param {number} snapshotIndex
+ * @return {Object.<string, Object>}
+ */
+Profiler.prototype.getBreakdowns = function(worldName, snapshotIndex) {
+ var snapshot = this._jsonData.snapshots[snapshotIndex];
+ if (!snapshot.worlds[worldName])
+ throw 'no world ' + worldName + ' in snapshot ' + index;
+
+ // Return breakdowns.
+ // TODO(junjianx): handle breakdown with arbitrary-level structure.
+ return snapshot.worlds[worldName].breakdown;
+};
+
+/**
+ * Get categories from fixed hard-coded worlds and breakdowns temporarily.
+ * TODO(junjianx): remove the hard-code and support general cases.
+ * @return {Array.<Object>}
+ */
+Profiler.prototype.getCategories = function() {
+ var categories = [];
+ var snapshotNum = this._jsonData.snapshots.length;
+
+ for (var snapshotIndex = 0; snapshotIndex < snapshotNum; ++snapshotIndex) {
+ // Initial categories object for one snapshot.
+ categories.push({});
+
+ // Handle breakdowns in malloc world.
+ var mallocBreakdown = this.getBreakdowns('malloc', snapshotIndex);
+ var mallocUnits = this.getUnits('malloc', snapshotIndex);
+ if (!mallocBreakdown['component'])
+ throw 'no breakdown ' + 'component' + ' in snapshot ' + snapshotIndex;
+
+ var componentBreakdown = mallocBreakdown['component'];
+ var componentMemory = 0;
+ Object.keys(componentBreakdown).forEach(function(breakdownName) {
+ var breakdown = componentBreakdown[breakdownName];
+ var memory = breakdown.units.reduce(function(previous, current) {
+ return previous + mallocUnits[current];
+ }, 0);
+ componentMemory += memory;
+
+ if (componentBreakdown['hidden'] === true)
+ return;
+ else
+ categories[snapshotIndex][breakdownName] = memory;
+ });
+
+ // Handle breakdowns in vm world.
+ var vmBreakdown = this.getBreakdowns('vm', snapshotIndex);
+ var vmUnits = this.getUnits('vm', snapshotIndex);
+ if (!vmBreakdown['map'])
+ throw 'no breakdown ' + 'map' + ' in snapshot ' + snapshotIndex;
+
+ var mapBreakdown = vmBreakdown['map'];
+
+ Object.keys(mapBreakdown).forEach(function(breakdownName) {
+ var breakdown = mapBreakdown[breakdownName];
+ var memory = breakdown.units.reduce(function(previous, current) {
+ return previous + vmUnits[current];
+ }, 0);
+
+ if (vmBreakdown['hidden'] === true)
+ return;
+ else if (breakdownName === 'mmap-tcmalloc')
+ categories[snapshotIndex]['tc-unused'] = memory - componentMemory;
+ else
+ categories[snapshotIndex][breakdownName] = memory;
+ });
+ }
+
+ return categories;
+};
+
+/**
+ * Generate lines for flot plotting.
+ * @param {Array.<Object>} categories
+ * @return {Array.<Object>}
+ */
+var generateLines = function(categories) {
+ var lines = {};
+ var snapshotNum = categories.length;
+
+ // Initialize lines with all zero.
+ categories.forEach(function(categories) {
+ Object.keys(categories).forEach(function(breakdownName) {
+ if (lines[breakdownName])
+ return;
+ lines[breakdownName] = [];
+ for (var i = 0; i < snapshotNum; ++i)
+ lines[breakdownName].push([i, 0]);
+ });
+ });
+
+ // Assignment lines with values of categories.
+ categories.forEach(function(categories, index) {
+ Object.keys(categories).forEach(function(breakdownName) {
+ lines[breakdownName][index] = [index, categories[breakdownName]];
+ });
+ });
+
+ return Object.keys(lines).map(function(breakdownName) {
+ return {
+ label: breakdownName,
+ data: lines[breakdownName]
+ };
+ });
+};
+
+$(function() {
+ // Read original data and plot.
+ $.getJSON('data/result.json', function(jsonData) {
+ var profiler = new Profiler(jsonData);
+ var categories = profiler.getCategories();
+ var lines = generateLines(categories);
+
+ // Plot stack graph.
+ $.plot('#plot', lines, {
+ series: {
+ stack: true,
+ lines: { show: true, fill: true }
+ }
+ });
+ });
+}); \ No newline at end of file