OLD | NEW |
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 Loading... |
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 Loading... |
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 384 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
1196 addDataToSnapshot: function(data) { | 1213 addDataToSnapshot: function(data) { |
1197 // TODO(eroman): We need to know which snapshot this data belongs to! | 1214 // TODO(eroman): We need to know which snapshot this data belongs to! |
1198 // For now we assume it is the most recent snapshot. | 1215 // For now we assume it is the most recent snapshot. |
1199 var snapshotIndex = this.snapshots_.length - 1; | 1216 var snapshotIndex = this.snapshots_.length - 1; |
1200 | 1217 |
1201 var snapshot = this.snapshots_[snapshotIndex]; | 1218 var snapshot = this.snapshots_[snapshotIndex]; |
1202 | 1219 |
1203 var pid = data.process_id; | 1220 var pid = data.process_id; |
1204 var ptype = data.process_type; | 1221 var ptype = data.process_type; |
1205 | 1222 |
| 1223 // Save the browser's representation of the data |
| 1224 snapshot.origData.push(data); |
| 1225 |
1206 // Augment each data row with the process information. | 1226 // Augment each data row with the process information. |
1207 var rows = data.list; | 1227 var rows = data.list; |
1208 for (var i = 0; i < rows.length; ++i) { | 1228 for (var i = 0; i < rows.length; ++i) { |
1209 // Transform the data from a dictionary to an array. This internal | 1229 // Transform the data from a dictionary to an array. This internal |
1210 // representation is more compact and faster to access. | 1230 // representation is more compact and faster to access. |
1211 var origRow = rows[i]; | 1231 var origRow = rows[i]; |
1212 var newRow = []; | 1232 var newRow = []; |
1213 | 1233 |
1214 newRow[KEY_PROCESS_ID] = pid; | 1234 newRow[KEY_PROCESS_ID] = pid; |
1215 newRow[KEY_PROCESS_TYPE] = ptype; | 1235 newRow[KEY_PROCESS_TYPE] = ptype; |
(...skipping 89 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
1305 | 1325 |
1306 /** | 1326 /** |
1307 * Re-draw the description that explains which snapshots are currently | 1327 * Re-draw the description that explains which snapshots are currently |
1308 * selected (if two snapshots were selected we explain that the *difference* | 1328 * selected (if two snapshots were selected we explain that the *difference* |
1309 * between them is being displayed). | 1329 * between them is being displayed). |
1310 */ | 1330 */ |
1311 updateSnapshotSelectionSummaryDiv_: function() { | 1331 updateSnapshotSelectionSummaryDiv_: function() { |
1312 var summaryDiv = $(SNAPSHOT_SELECTION_SUMMARY_ID); | 1332 var summaryDiv = $(SNAPSHOT_SELECTION_SUMMARY_ID); |
1313 | 1333 |
1314 var selectedSnapshots = this.getSelectedSnapshotIndexes_(); | 1334 var selectedSnapshots = this.getSelectedSnapshotIndexes_(); |
1315 if (selectedSnapshots.length == 1) { | 1335 if (selectedSnapshots.length == 0) { |
| 1336 // This can occur during an attempt to load a file or following file |
| 1337 // load failure. We just ignore it and move on. |
| 1338 } else if (selectedSnapshots.length == 1) { |
| 1339 // If only one snapshot is chosen then we will display that snapshot's |
| 1340 // data in its entirety. |
| 1341 this.flatData_ = this.snapshots_[selectedSnapshots[0]].flatData; |
| 1342 |
1316 // Don't bother displaying any text when just 1 snapshot is selected, | 1343 // Don't bother displaying any text when just 1 snapshot is selected, |
1317 // since it is obvious what this should do. | 1344 // since it is obvious what this should do. |
1318 summaryDiv.innerText = ''; | 1345 summaryDiv.innerText = ''; |
1319 } else if (selectedSnapshots.length == 2) { | 1346 } else if (selectedSnapshots.length == 2) { |
1320 // Otherwise if two snapshots were chosen, show the difference between | 1347 // Otherwise if two snapshots were chosen, show the difference between |
1321 // them. | 1348 // them. |
1322 var snapshot1 = this.snapshots_[selectedSnapshots[0]]; | 1349 var snapshot1 = this.snapshots_[selectedSnapshots[0]]; |
1323 var snapshot2 = this.snapshots_[selectedSnapshots[1]]; | 1350 var snapshot2 = this.snapshots_[selectedSnapshots[1]]; |
1324 | 1351 |
1325 var timeDeltaInSeconds = | 1352 var timeDeltaInSeconds = |
(...skipping 406 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
1732 $(TOGGLE_SNAPSHOTS_LINK_ID).onclick = | 1759 $(TOGGLE_SNAPSHOTS_LINK_ID).onclick = |
1733 toggleNodeDisplay.bind(null, $(SNAPSHOTS_ROW)); | 1760 toggleNodeDisplay.bind(null, $(SNAPSHOTS_ROW)); |
1734 | 1761 |
1735 $(MERGE_SIMILAR_THREADS_CHECKBOX_ID).onchange = | 1762 $(MERGE_SIMILAR_THREADS_CHECKBOX_ID).onchange = |
1736 this.onMergeSimilarThreadsCheckboxChanged_.bind(this); | 1763 this.onMergeSimilarThreadsCheckboxChanged_.bind(this); |
1737 | 1764 |
1738 $(RESET_DATA_LINK_ID).onclick = | 1765 $(RESET_DATA_LINK_ID).onclick = |
1739 g_browserBridge.sendResetData.bind(g_browserBridge); | 1766 g_browserBridge.sendResetData.bind(g_browserBridge); |
1740 | 1767 |
1741 $(TAKE_SNAPSHOT_BUTTON_ID).onclick = this.takeSnapshot_.bind(this); | 1768 $(TAKE_SNAPSHOT_BUTTON_ID).onclick = this.takeSnapshot_.bind(this); |
| 1769 |
| 1770 $(SAVE_SNAPSHOTS_BUTTON_ID).onclick = this.saveSnapshots_.bind(this); |
| 1771 $(SNAPSHOT_FILE_LOADER_ID).onchange = this.loadFileChanged_.bind(this); |
1742 }, | 1772 }, |
1743 | 1773 |
1744 takeSnapshot_: function() { | 1774 takeSnapshot_: function() { |
1745 // Start a new empty snapshot. Make note of the current time, so we know | 1775 // Start a new empty snapshot. Make note of the current time, so we know |
1746 // when the snaphot was taken. | 1776 // when the snaphot was taken. |
1747 this.snapshots_.push({flatData: [], time: getTimeMillis()}); | 1777 this.snapshots_.push({flatData: [], origData: [], time: getTimeMillis()}); |
1748 | 1778 |
1749 // Update the UI to reflect the new snapshot. | 1779 // Update the UI to reflect the new snapshot. |
1750 this.addSnapshotToList_(this.snapshots_.length - 1); | 1780 this.addSnapshotToList_(this.snapshots_.length - 1); |
1751 | 1781 |
1752 // Ask the browser for the profiling data. We will receive the data | 1782 // Ask the browser for the profiling data. We will receive the data |
1753 // later through a callback to addDataToSnapshot_(). | 1783 // later through a callback to addDataToSnapshot_(). |
1754 g_browserBridge.sendGetData(); | 1784 g_browserBridge.sendGetData(); |
1755 }, | 1785 }, |
1756 | 1786 |
| 1787 saveSnapshots_: function() { |
| 1788 var snapshots = []; |
| 1789 for (var i = 0; i < this.snapshots_.length; ++i) { |
| 1790 snapshots.push({ data: this.snapshots_[i].origData, |
| 1791 timestamp: Math.floor( |
| 1792 this.snapshots_[i].time / 1000) }); |
| 1793 } |
| 1794 |
| 1795 var dump = { |
| 1796 'userAgent': navigator.userAgent, |
| 1797 'version': 1, |
| 1798 'snapshots': snapshots |
| 1799 } |
| 1800 |
| 1801 var dumpText = JSON.stringify(dump, null, ' '); |
| 1802 var blobBuilder = new WebKitBlobBuilder(); |
| 1803 blobBuilder.append(dumpText, 'native'); |
| 1804 var textBlob = blobBuilder.getBlob('octet/stream'); |
| 1805 var blobUrl = window.webkitURL.createObjectURL(textBlob); |
| 1806 $(DOWNLOAD_IFRAME_ID).src = blobUrl; |
| 1807 }, |
| 1808 |
| 1809 loadFileChanged_: function() { |
| 1810 this.loadSnapshots_($(SNAPSHOT_FILE_LOADER_ID).files[0]) |
| 1811 }, |
| 1812 |
| 1813 loadSnapshots_: function(file) { |
| 1814 if (file) { |
| 1815 var fileReader = new FileReader(); |
| 1816 |
| 1817 fileReader.onload = this.onLoadSnapshotsFile_.bind(this, file); |
| 1818 fileReader.onerror = this.onLoadSnapshotsFileError_.bind(this, file); |
| 1819 |
| 1820 fileReader.readAsText(file); |
| 1821 } |
| 1822 }, |
| 1823 |
| 1824 onLoadSnapshotsFile_: function(file, event) { |
| 1825 try { |
| 1826 var parsed = null; |
| 1827 parsed = JSON.parse(event.target.result) |
| 1828 |
| 1829 if (parsed.version != 1) { |
| 1830 throw new Error('Unrecognized version: ' + parsed.version); |
| 1831 } |
| 1832 |
| 1833 if (parsed.snapshots.length < 1) { |
| 1834 throw new Error('File contains no data'); |
| 1835 } |
| 1836 |
| 1837 this.displayLoadedFile_(file, parsed); |
| 1838 this.hideFileLoadError_(); |
| 1839 } catch (error) { |
| 1840 this.displayFileLoadError_('File load failure: ' + error.message); |
| 1841 } |
| 1842 }, |
| 1843 |
| 1844 clearExistingSnapshots_: function() { |
| 1845 var tbody = $('snapshots-tbody'); |
| 1846 this.snapshots_ = []; |
| 1847 tbody.innerHTML = ''; |
| 1848 this.updateMergedDataSoon_(); |
| 1849 }, |
| 1850 |
| 1851 displayLoadedFile_: function (file, content) { |
| 1852 this.clearExistingSnapshots_(); |
| 1853 $(TAKE_SNAPSHOT_BUTTON_ID).disabled = true; |
| 1854 $(SAVE_SNAPSHOTS_BUTTON_ID).disabled = true; |
| 1855 |
| 1856 if (content.snapshots.length > 1) { |
| 1857 setNodeDisplay($(SNAPSHOTS_ROW), true); |
| 1858 } |
| 1859 |
| 1860 for (var i = 0; i < content.snapshots.length; ++i) { |
| 1861 var snapshot = content.snapshots[i]; |
| 1862 this.snapshots_.push({flatData: [], origData: [], |
| 1863 time: snapshot.timestamp * 1000}); |
| 1864 this.addSnapshotToList_(this.snapshots_.length - 1); |
| 1865 var snapshotData = snapshot.data; |
| 1866 for (var j = 0; j < snapshotData.length; ++j){ |
| 1867 this.addDataToSnapshot(snapshotData[j]); |
| 1868 } |
| 1869 } |
| 1870 this.redrawData_(); |
| 1871 }, |
| 1872 |
| 1873 onLoadSnapshotsFileError_: function(file, filedata) { |
| 1874 this.displayFileLoadError_('Error loading ' + file.name); |
| 1875 }, |
| 1876 |
| 1877 displayFileLoadError_: function(message) { |
| 1878 $(LOAD_ERROR_ID).textContent = message; |
| 1879 $(LOAD_ERROR_ID).hidden = false; |
| 1880 }, |
| 1881 |
| 1882 hideFileLoadError_: function() { |
| 1883 $(LOAD_ERROR_ID).textContent = ''; |
| 1884 $(LOAD_ERROR_ID).hidden = true; |
| 1885 }, |
| 1886 |
1757 getSnapshotCheckbox_: function(i) { | 1887 getSnapshotCheckbox_: function(i) { |
1758 return $(this.getSnapshotCheckboxId_(i)); | 1888 return $(this.getSnapshotCheckboxId_(i)); |
1759 }, | 1889 }, |
1760 | 1890 |
1761 getSnapshotCheckboxId_: function(i) { | 1891 getSnapshotCheckboxId_: function(i) { |
1762 return 'snapshotCheckbox-' + i; | 1892 return 'snapshotCheckbox-' + i; |
1763 }, | 1893 }, |
1764 | 1894 |
1765 addSnapshotToList_: function(i) { | 1895 addSnapshotToList_: function(i) { |
1766 var tbody = $('snapshots-tbody'); | 1896 var tbody = $('snapshots-tbody'); |
(...skipping 317 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
2084 groupKey.push(entry); | 2214 groupKey.push(entry); |
2085 } | 2215 } |
2086 | 2216 |
2087 return JSON.stringify(groupKey); | 2217 return JSON.stringify(groupKey); |
2088 }; | 2218 }; |
2089 }, | 2219 }, |
2090 }; | 2220 }; |
2091 | 2221 |
2092 return MainView; | 2222 return MainView; |
2093 })(); | 2223 })(); |
OLD | NEW |