Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(74)

Side by Side Diff: chrome/browser/resources/profiler.js

Issue 8918018: Support save/restore in about:profiler (Closed) Base URL: svn://svn.chromium.org/chrome/trunk/src
Patch Set: Created 9 years ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View unified diff | Download patch | Annotate | Revision Log
« no previous file with comments | « chrome/browser/resources/profiler.html ('k') | no next file » | no next file with comments »
Toggle Intra-line Diffs ('i') | Expand Comments ('e') | Collapse Comments ('c') | Show Comments Hide Comments ('s')
OLDNEW
1 // Copyright (c) 2011 The Chromium Authors. All rights reserved. 1 // Copyright (c) 2011 The Chromium Authors. All rights reserved.
2 // Use of this source code is governed by a BSD-style license that can be 2 // Use of this source code is governed by a BSD-style license that can be
3 // found in the LICENSE file. 3 // found in the LICENSE file.
4 4
5 var g_browserBridge; 5 var g_browserBridge;
6 var g_mainView; 6 var g_mainView;
7 7
8 // TODO(eroman): The handling of "max" across snapshots is not correct. 8 // TODO(eroman): The handling of "max" across snapshots is not correct.
9 // For starters the browser needs to be aware to generate new maximums. 9 // For starters the browser needs to be aware to generate new maximums.
10 // Secondly, we need to take into account the "max" of intermediary snapshots, 10 // Secondly, we need to take into account the "max" of intermediary snapshots,
(...skipping 86 matching lines...) Expand 10 before | Expand all | Expand 10 after
97 97
98 // The checkbox which controls whether things like "Worker Threads" and 98 // The checkbox which controls whether things like "Worker Threads" and
99 // "PAC threads" will be merged together. 99 // "PAC threads" will be merged together.
100 var MERGE_SIMILAR_THREADS_CHECKBOX_ID = 'merge-similar-threads-checkbox'; 100 var MERGE_SIMILAR_THREADS_CHECKBOX_ID = 'merge-similar-threads-checkbox';
101 101
102 var RESET_DATA_LINK_ID = 'reset-data-link'; 102 var RESET_DATA_LINK_ID = 'reset-data-link';
103 103
104 var TOGGLE_SNAPSHOTS_LINK_ID = 'snapshots-link'; 104 var TOGGLE_SNAPSHOTS_LINK_ID = 'snapshots-link';
105 var SNAPSHOTS_ROW = 'snapshots-row'; 105 var SNAPSHOTS_ROW = 'snapshots-row';
106 var SNAPSHOT_SELECTION_SUMMARY_ID = 'snapshot-selection-summary'; 106 var SNAPSHOT_SELECTION_SUMMARY_ID = 'snapshot-selection-summary';
107 var TAKE_SNAPSHOT_BUTTON_ID = 'snapshot-button'; 107 var TAKE_SNAPSHOT_BUTTON_ID = 'take-snapshot-button';
108
109 var SAVE_SNAPSHOTS_BUTTON_ID = 'save-snapshots-button';
110 var SNAPSHOT_FILE_LOADER_ID = 'snapshot-file-loader';
111 var LOAD_ERROR_ID = 'file-load-error';
112
113 var DOWNLOAD_IFRAME_ID = 'download-iframe';
108 114
109 // -------------------------------------------------------------------------- 115 // --------------------------------------------------------------------------
110 // Row keys 116 // Row keys
111 // -------------------------------------------------------------------------- 117 // --------------------------------------------------------------------------
112 118
113 // Each row of our data is an array of values rather than a dictionary. This 119 // Each row of our data is an array of values rather than a dictionary. This
114 // avoids some overhead from repeating the key string multiple times, and 120 // avoids some overhead from repeating the key string multiple times, and
115 // speeds up the property accesses a bit. The following keys are well-known 121 // speeds up the property accesses a bit. The following keys are well-known
116 // indexes into the array for various properties. 122 // indexes into the array for various properties.
117 // 123 //
(...skipping 674 matching lines...) Expand 10 before | Expand all | Expand 10 after
792 * Toggle a node between hidden/invisible. 798 * Toggle a node between hidden/invisible.
793 */ 799 */
794 function toggleNodeDisplay(n) { 800 function toggleNodeDisplay(n) {
795 if (n.style.display == '') { 801 if (n.style.display == '') {
796 n.style.display = 'none'; 802 n.style.display = 'none';
797 } else { 803 } else {
798 n.style.display = ''; 804 n.style.display = '';
799 } 805 }
800 } 806 }
801 807
808 /**
809 * Set the visibility state of a node.
810 */
811 function setNodeDisplay(n, visible) {
812 if (visible) {
813 n.style.display = '';
814 } else {
815 n.style.display = 'none';
816 }
817 }
818
802 // -------------------------------------------------------------------------- 819 // --------------------------------------------------------------------------
803 // Functions that augment, bucket, and compute aggregates for the input data. 820 // Functions that augment, bucket, and compute aggregates for the input data.
804 // -------------------------------------------------------------------------- 821 // --------------------------------------------------------------------------
805 822
806 /** 823 /**
807 * Adds new derived properties to row. Mutates the provided dictionary |e|. 824 * Adds new derived properties to row. Mutates the provided dictionary |e|.
808 */ 825 */
809 function augmentDataRow(e) { 826 function augmentDataRow(e) {
810 computeDataRowAverages(e); 827 computeDataRowAverages(e);
811 e[KEY_SOURCE_LOCATION] = e[KEY_FILE_NAME] + ' [' + e[KEY_LINE_NUMBER] + ']'; 828 e[KEY_SOURCE_LOCATION] = e[KEY_FILE_NAME] + ' [' + e[KEY_LINE_NUMBER] + ']';
(...skipping 378 matching lines...) Expand 10 before | Expand all | Expand 10 after
1190 addDataToSnapshot: function(data) { 1207 addDataToSnapshot: function(data) {
1191 // TODO(eroman): We need to know which snapshot this data belongs to! 1208 // TODO(eroman): We need to know which snapshot this data belongs to!
1192 // For now we assume it is the most recent snapshot. 1209 // For now we assume it is the most recent snapshot.
1193 var snapshotIndex = this.snapshots_.length - 1; 1210 var snapshotIndex = this.snapshots_.length - 1;
1194 1211
1195 var snapshot = this.snapshots_[snapshotIndex]; 1212 var snapshot = this.snapshots_[snapshotIndex];
1196 1213
1197 var pid = data.process_id; 1214 var pid = data.process_id;
1198 var ptype = data.process_type; 1215 var ptype = data.process_type;
1199 1216
1217 // Save the browser's representation of the data
1218 snapshot.origData.push(data);
1219
1200 // Augment each data row with the process information. 1220 // Augment each data row with the process information.
1201 var rows = data.list; 1221 var rows = data.list;
1202 for (var i = 0; i < rows.length; ++i) { 1222 for (var i = 0; i < rows.length; ++i) {
1203 // Transform the data from a dictionary to an array. This internal 1223 // Transform the data from a dictionary to an array. This internal
1204 // representation is more compact and faster to access. 1224 // representation is more compact and faster to access.
1205 var origRow = rows[i]; 1225 var origRow = rows[i];
1206 var newRow = []; 1226 var newRow = [];
1207 1227
1208 newRow[KEY_PROCESS_ID] = pid; 1228 newRow[KEY_PROCESS_ID] = pid;
1209 newRow[KEY_PROCESS_TYPE] = ptype; 1229 newRow[KEY_PROCESS_TYPE] = ptype;
(...skipping 88 matching lines...) Expand 10 before | Expand all | Expand 10 after
1298 1318
1299 /** 1319 /**
1300 * This function should be called any time a snapshot dependency for what is 1320 * This function should be called any time a snapshot dependency for what is
1301 * being displayed on the screen has changed. It will re-calculate the 1321 * being displayed on the screen has changed. It will re-calculate the
1302 * difference between the two snapshots and update flatData_. 1322 * difference between the two snapshots and update flatData_.
1303 */ 1323 */
1304 updateFlatData_: function() { 1324 updateFlatData_: function() {
1305 var summaryDiv = $(SNAPSHOT_SELECTION_SUMMARY_ID); 1325 var summaryDiv = $(SNAPSHOT_SELECTION_SUMMARY_ID);
1306 1326
1307 var selectedSnapshots = this.getSelectedSnapshotIndexes_(); 1327 var selectedSnapshots = this.getSelectedSnapshotIndexes_();
1308 if (selectedSnapshots.length == 1) { 1328 if (selectedSnapshots.length == 0) {
1329 // This can occur during an attempt to load a file or following file
1330 // load failure. We just ignore it and move on.
1331 } else if (selectedSnapshots.length == 1) {
1309 // If only one snapshot is chosen then we will display that snapshot's 1332 // If only one snapshot is chosen then we will display that snapshot's
1310 // data in its entirety. 1333 // data in its entirety.
1311 this.flatData_ = this.snapshots_[selectedSnapshots[0]].flatData; 1334 this.flatData_ = this.snapshots_[selectedSnapshots[0]].flatData;
1312 1335
1313 // Don't bother displaying any text when just 1 snapshot is selected, 1336 // Don't bother displaying any text when just 1 snapshot is selected,
1314 // since it is obvious what this should do. 1337 // since it is obvious what this should do.
1315 summaryDiv.innerText = ''; 1338 summaryDiv.innerText = '';
1316 } else if (selectedSnapshots.length == 2) { 1339 } else if (selectedSnapshots.length == 2) {
1317 // Otherwise if two snapshots were chosen, show the difference between 1340 // Otherwise if two snapshots were chosen, show the difference between
1318 // them. 1341 // them.
(...skipping 383 matching lines...) Expand 10 before | Expand all | Expand 10 after
1702 $(TOGGLE_SNAPSHOTS_LINK_ID).onclick = 1725 $(TOGGLE_SNAPSHOTS_LINK_ID).onclick =
1703 toggleNodeDisplay.bind(null, $(SNAPSHOTS_ROW)); 1726 toggleNodeDisplay.bind(null, $(SNAPSHOTS_ROW));
1704 1727
1705 $(MERGE_SIMILAR_THREADS_CHECKBOX_ID).onchange = 1728 $(MERGE_SIMILAR_THREADS_CHECKBOX_ID).onchange =
1706 this.onMergeSimilarThreadsCheckboxChanged_.bind(this); 1729 this.onMergeSimilarThreadsCheckboxChanged_.bind(this);
1707 1730
1708 $(RESET_DATA_LINK_ID).onclick = 1731 $(RESET_DATA_LINK_ID).onclick =
1709 g_browserBridge.sendResetData.bind(g_browserBridge); 1732 g_browserBridge.sendResetData.bind(g_browserBridge);
1710 1733
1711 $(TAKE_SNAPSHOT_BUTTON_ID).onclick = this.takeSnapshot_.bind(this); 1734 $(TAKE_SNAPSHOT_BUTTON_ID).onclick = this.takeSnapshot_.bind(this);
1735
1736 $(SAVE_SNAPSHOTS_BUTTON_ID).onclick = this.saveSnapshots_.bind(this);
1737 $(SNAPSHOT_FILE_LOADER_ID).onchange = this.loadFileChanged_.bind(this);
1712 }, 1738 },
1713 1739
1714 takeSnapshot_: function() { 1740 takeSnapshot_: function() {
1715 // Start a new empty snapshot. Make note of the current time, so we know 1741 // Start a new empty snapshot. Make note of the current time, so we know
1716 // when the snaphot was taken. 1742 // when the snaphot was taken.
1717 this.snapshots_.push({flatData: [], time: getTimeMillis()}); 1743 this.snapshots_.push({flatData: [], origData: [], time: getTimeMillis()});
1718 1744
1719 // Update the UI to reflect the new snapshot. 1745 // Update the UI to reflect the new snapshot.
1720 this.addSnapshotToList_(this.snapshots_.length - 1); 1746 this.addSnapshotToList_(this.snapshots_.length - 1);
1721 1747
1722 // Ask the browser for the profiling data. We will receive the data 1748 // Ask the browser for the profiling data. We will receive the data
1723 // later through a callback to addDataToSnapshot_(). 1749 // later through a callback to addDataToSnapshot_().
1724 g_browserBridge.sendGetData(); 1750 g_browserBridge.sendGetData();
1725 }, 1751 },
1726 1752
1753 saveSnapshots_: function() {
1754 var snapshots = [];
1755 for (var i = 0; i < this.snapshots_.length; ++i) {
1756 snapshots.push({ data: this.snapshots_[i].origData,
1757 timestamp: this.snapshots_[i].time });
1758 }
1759
1760 var dump = {
1761 // 'browser_version': '' // FIXME fetch this somehow
eroman 2011/12/12 23:14:28 you could include the user agent (navigator.userAg
1762 'snapshots': snapshots
eroman 2011/12/12 23:14:28 I suggest putting a version field in the format to
1763 }
1764
1765 var dumpText = JSON.stringify(dump, null, ' ')
1766 var blobBuilder = new WebKitBlobBuilder();
1767 blobBuilder.append(dumpText, 'native');
1768 var textBlob = blobBuilder.getBlob('octet/stream');
1769 var blobUrl = window.webkitURL.createObjectURL(textBlob);
1770 $(DOWNLOAD_IFRAME_ID).src = blobUrl;
1771 },
1772
1773 loadFileChanged_: function() {
1774 this.loadSnapshots_($(SNAPSHOT_FILE_LOADER_ID).files[0])
1775 },
1776
1777 loadSnapshots_: function(file) {
1778 if (file) {
1779 var fileReader = new FileReader();
1780
1781 fileReader.onload = this.onLoadSnapshotsFile_.bind(this, file);
1782 fileReader.onerror = this.onLoadSnapshotsFileError_.bind(this, file);
1783
1784 fileReader.readAsText(file);
1785 }
1786 },
1787
1788 onLoadSnapshotsFile_: function(file, event) {
1789 try {
1790 var parsed = null;
1791 parsed = JSON.parse(event.target.result)
1792
1793 this.displayLoadedFile_(file, parsed);
1794 this.hideFileLoadError_();
1795 } catch (error) {
1796 this.displayFileLoadError_('File load failure: ' + error.message);
1797 }
1798 },
1799
1800 clearExistingSnapshots_: function() {
1801 var tbody = $('snapshots-tbody');
1802 this.snapshots_ = [];
1803 while (tbody.hasChildNodes()) {
eroman 2011/12/12 23:14:28 A more typical way to empty a node is: tbody.inne
1804 tbody.removeChild(tbody.lastChild);
1805 }
1806 this.updateFlatDataSoon_();
1807 },
1808
1809 displayLoadedFile_: function (file, content) {
1810 this.clearExistingSnapshots_();
1811 $(TAKE_SNAPSHOT_BUTTON_ID).disabled = true;
1812 $(SAVE_SNAPSHOTS_BUTTON_ID).disabled = true;
1813
1814 if (content.snapshots.length > 1) {
1815 setNodeDisplay($(SNAPSHOTS_ROW), true);
1816 }
1817
1818 for (var i = 0; i < content.snapshots.length; ++i) {
1819 var snapshot = content.snapshots[i];
1820 this.snapshots_.push({flatData: [], origData: [],
1821 time: snapshot.timestamp});
1822 this.addSnapshotToList_(this.snapshots_.length - 1);
1823 var snapshotData = snapshot.data;
1824 for (var j = 0; j < snapshotData.length; ++j){
1825 this.addDataToSnapshot(snapshotData[j]);
1826 }
1827 }
1828 this.redrawData_();
1829 },
1830
1831 onLoadSnapshotsFileError_: function(file, filedata) {
1832 this.displayFileLoadError_('Error loading ' + file.name);
1833 },
1834
1835 displayFileLoadError_: function(message) {
1836 $(LOAD_ERROR_ID).textContent = message;
1837 $(LOAD_ERROR_ID).hidden = false;
1838 },
1839
1840 hideFileLoadError_: function() {
1841 $(LOAD_ERROR_ID).textContent = '';
1842 $(LOAD_ERROR_ID).hidden = true;
1843 },
1844
1727 getSnapshotCheckbox_: function(i) { 1845 getSnapshotCheckbox_: function(i) {
1728 return $(this.getSnapshotCheckboxId_(i)); 1846 return $(this.getSnapshotCheckboxId_(i));
1729 }, 1847 },
1730 1848
1731 getSnapshotCheckboxId_: function(i) { 1849 getSnapshotCheckboxId_: function(i) {
1732 return 'snapshotCheckbox-' + i; 1850 return 'snapshotCheckbox-' + i;
1733 }, 1851 },
1734 1852
1735 addSnapshotToList_: function(i) { 1853 addSnapshotToList_: function(i) {
1736 var tbody = $('snapshots-tbody'); 1854 var tbody = $('snapshots-tbody');
(...skipping 316 matching lines...) Expand 10 before | Expand all | Expand 10 after
2053 groupKey.push(entry); 2171 groupKey.push(entry);
2054 } 2172 }
2055 2173
2056 return JSON.stringify(groupKey); 2174 return JSON.stringify(groupKey);
2057 }; 2175 };
2058 }, 2176 },
2059 }; 2177 };
2060 2178
2061 return MainView; 2179 return MainView;
2062 })(); 2180 })();
OLDNEW
« no previous file with comments | « chrome/browser/resources/profiler.html ('k') | no next file » | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698