OLD | NEW |
1 // Copyright (c) 2012 The Chromium Authors. All rights reserved. | 1 // Copyright (c) 2012 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 12 matching lines...) Expand all Loading... |
23 /** | 23 /** |
24 * This class provides a "bridge" for communicating between the javascript and | 24 * This class provides a "bridge" for communicating between the javascript and |
25 * the browser. Used as a singleton. | 25 * the browser. Used as a singleton. |
26 */ | 26 */ |
27 var BrowserBridge = (function() { | 27 var BrowserBridge = (function() { |
28 'use strict'; | 28 'use strict'; |
29 | 29 |
30 /** | 30 /** |
31 * @constructor | 31 * @constructor |
32 */ | 32 */ |
33 function BrowserBridge() { | 33 function BrowserBridge() {} |
34 } | |
35 | 34 |
36 BrowserBridge.prototype = { | 35 BrowserBridge.prototype = { |
37 //-------------------------------------------------------------------------- | 36 //-------------------------------------------------------------------------- |
38 // Messages sent to the browser | 37 // Messages sent to the browser |
39 //-------------------------------------------------------------------------- | 38 //-------------------------------------------------------------------------- |
40 | 39 |
41 sendGetData: function() { | 40 sendGetData: function() { |
42 chrome.send('getData'); | 41 chrome.send('getData'); |
43 }, | 42 }, |
44 | 43 |
(...skipping 130 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
175 consume: function(e) { | 174 consume: function(e) { |
176 this.valuesSet_[e[this.key_]] = true; | 175 this.valuesSet_[e[this.key_]] = true; |
177 }, | 176 }, |
178 | 177 |
179 getValueAsText: function() { | 178 getValueAsText: function() { |
180 return getDictionaryKeys(this.valuesSet_).length + ' unique'; | 179 return getDictionaryKeys(this.valuesSet_).length + ' unique'; |
181 }, | 180 }, |
182 }; | 181 }; |
183 | 182 |
184 return { | 183 return { |
185 create: function(key) { return new Aggregator(key); } | 184 create: function(key) { |
| 185 return new Aggregator(key); |
| 186 } |
186 }; | 187 }; |
187 })(); | 188 })(); |
188 | 189 |
189 /** | 190 /** |
190 * This aggregator sums a numeric field. | 191 * This aggregator sums a numeric field. |
191 */ | 192 */ |
192 var SumAggregator = (function() { | 193 var SumAggregator = (function() { |
193 function Aggregator(key) { | 194 function Aggregator(key) { |
194 this.key_ = key; | 195 this.key_ = key; |
195 this.sum_ = 0; | 196 this.sum_ = 0; |
196 } | 197 } |
197 | 198 |
198 Aggregator.prototype = { | 199 Aggregator.prototype = { |
199 consume: function(e) { | 200 consume: function(e) { |
200 this.sum_ += e[this.key_]; | 201 this.sum_ += e[this.key_]; |
201 }, | 202 }, |
202 | 203 |
203 getValue: function() { | 204 getValue: function() { |
204 return this.sum_; | 205 return this.sum_; |
205 }, | 206 }, |
206 | 207 |
207 getValueAsText: function() { | 208 getValueAsText: function() { |
208 return formatNumberAsText(this.getValue()); | 209 return formatNumberAsText(this.getValue()); |
209 }, | 210 }, |
210 }; | 211 }; |
211 | 212 |
212 return { | 213 return { |
213 create: function(key) { return new Aggregator(key); } | 214 create: function(key) { |
| 215 return new Aggregator(key); |
| 216 } |
214 }; | 217 }; |
215 })(); | 218 })(); |
216 | 219 |
217 /** | 220 /** |
218 * This aggregator computes an average by summing two | 221 * This aggregator computes an average by summing two |
219 * numeric fields, and then dividing the totals. | 222 * numeric fields, and then dividing the totals. |
220 */ | 223 */ |
221 var AvgAggregator = (function() { | 224 var AvgAggregator = (function() { |
222 function Aggregator(numeratorKey, divisorKey) { | 225 function Aggregator(numeratorKey, divisorKey) { |
223 this.numeratorKey_ = numeratorKey; | 226 this.numeratorKey_ = numeratorKey; |
(...skipping 87 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
311 getValue: function() { | 314 getValue: function() { |
312 return this.max_; | 315 return this.max_; |
313 }, | 316 }, |
314 | 317 |
315 getValueAsText: function() { | 318 getValueAsText: function() { |
316 return formatNumberAsText(this.getValue()); | 319 return formatNumberAsText(this.getValue()); |
317 }, | 320 }, |
318 }; | 321 }; |
319 | 322 |
320 return { | 323 return { |
321 create: function(key) { return new Aggregator(key); } | 324 create: function(key) { |
| 325 return new Aggregator(key); |
| 326 } |
322 }; | 327 }; |
323 })(); | 328 })(); |
324 | 329 |
325 // -------------------------------------------------------------------------- | 330 // -------------------------------------------------------------------------- |
326 // Key properties | 331 // Key properties |
327 // -------------------------------------------------------------------------- | 332 // -------------------------------------------------------------------------- |
328 | 333 |
329 // Custom comparator for thread names (sorts main thread and IO thread | 334 // Custom comparator for thread names (sorts main thread and IO thread |
330 // higher than would happen lexicographically.) | 335 // higher than would happen lexicographically.) |
331 var threadNameComparator = | 336 var threadNameComparator = createLexicographicComparatorWithExceptions([ |
332 createLexicographicComparatorWithExceptions([ | 337 'CrBrowserMain', |
333 'CrBrowserMain', | 338 'Chrome_IOThread', |
334 'Chrome_IOThread', | 339 'Chrome_FileThread', |
335 'Chrome_FileThread', | 340 'Chrome_HistoryThread', |
336 'Chrome_HistoryThread', | 341 'Chrome_DBThread', |
337 'Chrome_DBThread', | 342 'Still_Alive', |
338 'Still_Alive', | 343 ]); |
339 ]); | |
340 | 344 |
341 function diffFuncForCount(a, b) { | 345 function diffFuncForCount(a, b) { |
342 return b - a; | 346 return b - a; |
343 } | 347 } |
344 | 348 |
345 function diffFuncForMax(a, b) { | 349 function diffFuncForMax(a, b) { |
346 return b; | 350 return b; |
347 } | 351 } |
348 | 352 |
349 /** | 353 /** |
(...skipping 135 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
485 sortDescending: true, | 489 sortDescending: true, |
486 textPrinter: formatNumberAsText, | 490 textPrinter: formatNumberAsText, |
487 aggregator: AvgAggregator.create(KEY_MEMORY_FREE_OPS, KEY_COUNT), | 491 aggregator: AvgAggregator.create(KEY_MEMORY_FREE_OPS, KEY_COUNT), |
488 }; | 492 }; |
489 | 493 |
490 KEY_PROPERTIES[KEY_MEMORY_AVG_NET_BYTES] = { | 494 KEY_PROPERTIES[KEY_MEMORY_AVG_NET_BYTES] = { |
491 name: 'Avg Net Bytes', | 495 name: 'Avg Net Bytes', |
492 cellAlignment: 'right', | 496 cellAlignment: 'right', |
493 sortDescending: true, | 497 sortDescending: true, |
494 textPrinter: formatNumberAsText, | 498 textPrinter: formatNumberAsText, |
495 aggregator: AvgDiffAggregator.create(KEY_MEMORY_ALLOCATED_BYTES, | 499 aggregator: AvgDiffAggregator.create( |
496 KEY_MEMORY_FREED_BYTES, KEY_COUNT), | 500 KEY_MEMORY_ALLOCATED_BYTES, KEY_MEMORY_FREED_BYTES, KEY_COUNT), |
497 }; | 501 }; |
498 | 502 |
499 KEY_PROPERTIES[KEY_MEMORY_ALLOC_OPS] = { | 503 KEY_PROPERTIES[KEY_MEMORY_ALLOC_OPS] = { |
500 name: 'Allocation count', | 504 name: 'Allocation count', |
501 cellAlignment: 'right', | 505 cellAlignment: 'right', |
502 sortDescending: true, | 506 sortDescending: true, |
503 textPrinter: formatNumberAsText, | 507 textPrinter: formatNumberAsText, |
504 inputJsonKey: 'death_data.alloc_ops', | 508 inputJsonKey: 'death_data.alloc_ops', |
505 aggregator: SumAggregator, | 509 aggregator: SumAggregator, |
506 diff: diffFuncForCount, | 510 diff: diffFuncForCount, |
(...skipping 244 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
751 } | 755 } |
752 | 756 |
753 /** | 757 /** |
754 * Formats the number |x| as a decimal integer. Strips off any decimal parts, | 758 * Formats the number |x| as a decimal integer. Strips off any decimal parts, |
755 * and comma separates the number every 3 characters. | 759 * and comma separates the number every 3 characters. |
756 */ | 760 */ |
757 function formatNumberAsText(x) { | 761 function formatNumberAsText(x) { |
758 var orig = x.toFixed(0); | 762 var orig = x.toFixed(0); |
759 | 763 |
760 var parts = []; | 764 var parts = []; |
761 for (var end = orig.length; end > 0; ) { | 765 for (var end = orig.length; end > 0;) { |
762 var chunk = Math.min(end, 3); | 766 var chunk = Math.min(end, 3); |
763 parts.push(orig.substr(end - chunk, chunk)); | 767 parts.push(orig.substr(end - chunk, chunk)); |
764 end -= chunk; | 768 end -= chunk; |
765 } | 769 } |
766 return parts.reverse().join(','); | 770 return parts.reverse().join(','); |
767 } | 771 } |
768 | 772 |
769 /** | 773 /** |
770 * Simple comparator function which works for both strings and numbers. | 774 * Simple comparator function which works for both strings and numbers. |
771 */ | 775 */ |
(...skipping 71 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
843 var textNode = parent.ownerDocument.createTextNode(text); | 847 var textNode = parent.ownerDocument.createTextNode(text); |
844 parent.appendChild(textNode); | 848 parent.appendChild(textNode); |
845 return textNode; | 849 return textNode; |
846 } | 850 } |
847 | 851 |
848 /** | 852 /** |
849 * Deletes all the strings in |array| which appear in |valuesToDelete|. | 853 * Deletes all the strings in |array| which appear in |valuesToDelete|. |
850 */ | 854 */ |
851 function deleteValuesFromArray(array, valuesToDelete) { | 855 function deleteValuesFromArray(array, valuesToDelete) { |
852 var valueSet = arrayToSet(valuesToDelete); | 856 var valueSet = arrayToSet(valuesToDelete); |
853 for (var i = 0; i < array.length; ) { | 857 for (var i = 0; i < array.length;) { |
854 if (valueSet[array[i]]) { | 858 if (valueSet[array[i]]) { |
855 array.splice(i, 1); | 859 array.splice(i, 1); |
856 } else { | 860 } else { |
857 i++; | 861 i++; |
858 } | 862 } |
859 } | 863 } |
860 } | 864 } |
861 | 865 |
862 /** | 866 /** |
863 * Deletes all the repeated ocurrences of strings in |array|. | 867 * Deletes all the repeated ocurrences of strings in |array|. |
864 */ | 868 */ |
865 function deleteDuplicateStringsFromArray(array) { | 869 function deleteDuplicateStringsFromArray(array) { |
866 // Build up set of each entry in array. | 870 // Build up set of each entry in array. |
867 var seenSoFar = {}; | 871 var seenSoFar = {}; |
868 | 872 |
869 for (var i = 0; i < array.length; ) { | 873 for (var i = 0; i < array.length;) { |
870 var value = array[i]; | 874 var value = array[i]; |
871 if (seenSoFar[value]) { | 875 if (seenSoFar[value]) { |
872 array.splice(i, 1); | 876 array.splice(i, 1); |
873 } else { | 877 } else { |
874 seenSoFar[value] = true; | 878 seenSoFar[value] = true; |
875 i++; | 879 i++; |
876 } | 880 } |
877 } | 881 } |
878 } | 882 } |
879 | 883 |
(...skipping 35 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
915 checkbox.type = 'checkbox'; | 919 checkbox.type = 'checkbox'; |
916 addText(labelNode, label); | 920 addText(labelNode, label); |
917 return checkbox; | 921 return checkbox; |
918 } | 922 } |
919 | 923 |
920 /** | 924 /** |
921 * Return the last component in a path which is separated by either forward | 925 * Return the last component in a path which is separated by either forward |
922 * slashes or backslashes. | 926 * slashes or backslashes. |
923 */ | 927 */ |
924 function getFilenameFromPath(path) { | 928 function getFilenameFromPath(path) { |
925 var lastSlash = Math.max(path.lastIndexOf('/'), | 929 var lastSlash = Math.max(path.lastIndexOf('/'), path.lastIndexOf('\\')); |
926 path.lastIndexOf('\\')); | |
927 if (lastSlash == -1) | 930 if (lastSlash == -1) |
928 return path; | 931 return path; |
929 | 932 |
930 return path.substr(lastSlash + 1); | 933 return path.substr(lastSlash + 1); |
931 } | 934 } |
932 | 935 |
933 /** | 936 /** |
934 * Returns the current time in milliseconds since unix epoch. | 937 * Returns the current time in milliseconds since unix epoch. |
935 */ | 938 */ |
936 function getTimeMillis() { | 939 function getTimeMillis() { |
(...skipping 36 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
973 | 976 |
974 function computeDataRowAverages(e) { | 977 function computeDataRowAverages(e) { |
975 e[KEY_AVG_QUEUE_TIME] = e[KEY_QUEUE_TIME] / e[KEY_COUNT]; | 978 e[KEY_AVG_QUEUE_TIME] = e[KEY_QUEUE_TIME] / e[KEY_COUNT]; |
976 e[KEY_AVG_RUN_TIME] = e[KEY_RUN_TIME] / e[KEY_COUNT]; | 979 e[KEY_AVG_RUN_TIME] = e[KEY_RUN_TIME] / e[KEY_COUNT]; |
977 | 980 |
978 if (loadTimeData.getBoolean('enableMemoryTaskProfiler')) { | 981 if (loadTimeData.getBoolean('enableMemoryTaskProfiler')) { |
979 e[KEY_MEMORY_AVG_ALLOC_OPS] = e[KEY_MEMORY_ALLOC_OPS] / e[KEY_COUNT]; | 982 e[KEY_MEMORY_AVG_ALLOC_OPS] = e[KEY_MEMORY_ALLOC_OPS] / e[KEY_COUNT]; |
980 e[KEY_MEMORY_AVG_FREE_OPS] = e[KEY_MEMORY_FREE_OPS] / e[KEY_COUNT]; | 983 e[KEY_MEMORY_AVG_FREE_OPS] = e[KEY_MEMORY_FREE_OPS] / e[KEY_COUNT]; |
981 e[KEY_MEMORY_AVG_NET_BYTES] = | 984 e[KEY_MEMORY_AVG_NET_BYTES] = |
982 (e[KEY_MEMORY_ALLOCATED_BYTES] - e[KEY_MEMORY_FREED_BYTES]) / | 985 (e[KEY_MEMORY_ALLOCATED_BYTES] - e[KEY_MEMORY_FREED_BYTES]) / |
983 e[KEY_COUNT]; | 986 e[KEY_COUNT]; |
984 } | 987 } |
985 } | 988 } |
986 | 989 |
987 /** | 990 /** |
988 * Creates and initializes an aggregator object for each key in |columns|. | 991 * Creates and initializes an aggregator object for each key in |columns|. |
989 * Returns an array whose keys are values from |columns|, and whose | 992 * Returns an array whose keys are values from |columns|, and whose |
990 * values are Aggregator instances. | 993 * values are Aggregator instances. |
991 */ | 994 */ |
992 function initializeAggregates(columns) { | 995 function initializeAggregates(columns) { |
993 var aggregates = []; | 996 var aggregates = []; |
(...skipping 38 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
1032 * order). | 1035 * order). |
1033 * | 1036 * |
1034 * If |mergeSimilarThreads| is true, then threads with a similar name will be | 1037 * If |mergeSimilarThreads| is true, then threads with a similar name will be |
1035 * considered equivalent. For instance, "WorkerThread-1" and "WorkerThread-2" | 1038 * considered equivalent. For instance, "WorkerThread-1" and "WorkerThread-2" |
1036 * will be remapped to "WorkerThread-*". | 1039 * will be remapped to "WorkerThread-*". |
1037 * | 1040 * |
1038 * If |outputAsDictionary| is false then the merged rows will be returned as a | 1041 * If |outputAsDictionary| is false then the merged rows will be returned as a |
1039 * flat list. Otherwise the result will be a dictionary, where each row | 1042 * flat list. Otherwise the result will be a dictionary, where each row |
1040 * has a unique key. | 1043 * has a unique key. |
1041 */ | 1044 */ |
1042 function mergeRows(origRows, mergeKeys, mergeSimilarThreads, | 1045 function mergeRows( |
1043 outputAsDictionary) { | 1046 origRows, mergeKeys, mergeSimilarThreads, outputAsDictionary) { |
1044 // Define a translation function for each property. Normally we copy over | 1047 // Define a translation function for each property. Normally we copy over |
1045 // properties as-is, but if we have been asked to "merge similar threads" we | 1048 // properties as-is, but if we have been asked to "merge similar threads" we |
1046 // we will remap the thread names that end in a numeric suffix. | 1049 // we will remap the thread names that end in a numeric suffix. |
1047 var propertyGetterFunc; | 1050 var propertyGetterFunc; |
1048 | 1051 |
1049 if (mergeSimilarThreads) { | 1052 if (mergeSimilarThreads) { |
1050 propertyGetterFunc = function(row, key) { | 1053 propertyGetterFunc = function(row, key) { |
1051 var value = row[key]; | 1054 var value = row[key]; |
1052 // If the property is a thread name, try to remap it. | 1055 // If the property is a thread name, try to remap it. |
1053 if (key == KEY_BIRTH_THREAD || key == KEY_DEATH_THREAD) { | 1056 if (key == KEY_BIRTH_THREAD || key == KEY_DEATH_THREAD) { |
1054 var m = /^(.*[^\d])(\d+)$/.exec(value); | 1057 var m = /^(.*[^\d])(\d+)$/.exec(value); |
1055 if (m) | 1058 if (m) |
1056 value = m[1] + '*'; | 1059 value = m[1] + '*'; |
1057 } | 1060 } |
1058 return value; | 1061 return value; |
1059 }; | 1062 }; |
1060 } else { | 1063 } else { |
1061 propertyGetterFunc = function(row, key) { return row[key]; }; | 1064 propertyGetterFunc = function(row, key) { |
| 1065 return row[key]; |
| 1066 }; |
1062 } | 1067 } |
1063 | 1068 |
1064 // Determine which sets of properties a row needs to match on to be | 1069 // Determine which sets of properties a row needs to match on to be |
1065 // considered identical to another row. | 1070 // considered identical to another row. |
1066 var identityKeys = IDENTITY_KEYS.slice(0); | 1071 var identityKeys = IDENTITY_KEYS.slice(0); |
1067 deleteValuesFromArray(identityKeys, mergeKeys); | 1072 deleteValuesFromArray(identityKeys, mergeKeys); |
1068 | 1073 |
1069 // Set |aggregateKeys| to everything else, since we will be aggregating | 1074 // Set |aggregateKeys| to everything else, since we will be aggregating |
1070 // their value as part of the merge. | 1075 // their value as part of the merge. |
1071 var aggregateKeys = ALL_KEYS.slice(0); | 1076 var aggregateKeys = ALL_KEYS.slice(0); |
(...skipping 47 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
1119 * | 1124 * |
1120 * Rows in data1 and data2 are expected to use the same scheme for the keys. | 1125 * Rows in data1 and data2 are expected to use the same scheme for the keys. |
1121 * In other words, data1[k] is considered the analagous row to data2[k]. | 1126 * In other words, data1[k] is considered the analagous row to data2[k]. |
1122 */ | 1127 */ |
1123 function subtractSnapshots(data1, data2, columnsToExclude) { | 1128 function subtractSnapshots(data1, data2, columnsToExclude) { |
1124 // These columns are computed from the other columns. We won't bother | 1129 // These columns are computed from the other columns. We won't bother |
1125 // diffing/aggregating these, but rather will derive them again from the | 1130 // diffing/aggregating these, but rather will derive them again from the |
1126 // final row. | 1131 // final row. |
1127 var COMPUTED_AGGREGATE_KEYS = [KEY_AVG_QUEUE_TIME, KEY_AVG_RUN_TIME]; | 1132 var COMPUTED_AGGREGATE_KEYS = [KEY_AVG_QUEUE_TIME, KEY_AVG_RUN_TIME]; |
1128 if (loadTimeData.getBoolean('enableMemoryTaskProfiler')) { | 1133 if (loadTimeData.getBoolean('enableMemoryTaskProfiler')) { |
1129 COMPUTED_AGGREGATE_KEYS = COMPUTED_AGGREGATE_KEYS.concat([ | 1134 COMPUTED_AGGREGATE_KEYS = COMPUTED_AGGREGATE_KEYS.concat([ |
1130 KEY_MEMORY_AVG_ALLOC_OPS, | 1135 KEY_MEMORY_AVG_ALLOC_OPS, KEY_MEMORY_AVG_FREE_OPS, |
1131 KEY_MEMORY_AVG_FREE_OPS, | 1136 KEY_MEMORY_AVG_NET_BYTES |
1132 KEY_MEMORY_AVG_NET_BYTES]); | 1137 ]); |
1133 } | 1138 } |
1134 | 1139 |
1135 // These are the keys which determine row equality. Since we are not doing | 1140 // These are the keys which determine row equality. Since we are not doing |
1136 // any merging yet at this point, it is simply the list of all identity | 1141 // any merging yet at this point, it is simply the list of all identity |
1137 // columns. | 1142 // columns. |
1138 var identityKeys = IDENTITY_KEYS.slice(0); | 1143 var identityKeys = IDENTITY_KEYS.slice(0); |
1139 deleteValuesFromArray(identityKeys, columnsToExclude); | 1144 deleteValuesFromArray(identityKeys, columnsToExclude); |
1140 | 1145 |
1141 // The columns to compute via aggregation is everything else. | 1146 // The columns to compute via aggregation is everything else. |
1142 var aggregateKeys = ALL_KEYS.slice(0); | 1147 var aggregateKeys = ALL_KEYS.slice(0); |
(...skipping 85 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
1228 // builds. | 1233 // builds. |
1229 var m = /^(.*) \[(\d+)\]$/.exec(text); | 1234 var m = /^(.*) \[(\d+)\]$/.exec(text); |
1230 if (m) { | 1235 if (m) { |
1231 var filepath = m[1]; | 1236 var filepath = m[1]; |
1232 var filename = getFilenameFromPath(filepath); | 1237 var filename = getFilenameFromPath(filepath); |
1233 var linenumber = m[2]; | 1238 var linenumber = m[2]; |
1234 | 1239 |
1235 var link = addNode(td, 'a', filename + ' [' + linenumber + ']'); | 1240 var link = addNode(td, 'a', filename + ' [' + linenumber + ']'); |
1236 | 1241 |
1237 link.href = 'https://code.google.com/p/chromium/codesearch#search/&q=' + | 1242 link.href = 'https://code.google.com/p/chromium/codesearch#search/&q=' + |
1238 encodeURIComponent(filename) + ':' + linenumber + | 1243 encodeURIComponent(filename) + ':' + linenumber + |
1239 '&sq=package:chromium&type=cs'; | 1244 '&sq=package:chromium&type=cs'; |
1240 link.target = '_blank'; | 1245 link.target = '_blank'; |
1241 return; | 1246 return; |
1242 } | 1247 } |
1243 } | 1248 } |
1244 | 1249 |
1245 // String values can get pretty long. If the string contains no spaces, then | 1250 // String values can get pretty long. If the string contains no spaces, then |
1246 // CSS fails to wrap it, and it overflows the cell causing the table to get | 1251 // CSS fails to wrap it, and it overflows the cell causing the table to get |
1247 // really big. We solve this using a hack: insert a <wbr> element after | 1252 // really big. We solve this using a hack: insert a <wbr> element after |
1248 // every single character. This will allow the rendering engine to wrap the | 1253 // every single character. This will allow the rendering engine to wrap the |
1249 // value, and hence avoid it overflowing! | 1254 // value, and hence avoid it overflowing! |
(...skipping 252 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
1502 // Otherwise if two snapshots were chosen, show the difference between | 1507 // Otherwise if two snapshots were chosen, show the difference between |
1503 // them. | 1508 // them. |
1504 var snapshot1 = this.snapshots_[selectedSnapshots[0]]; | 1509 var snapshot1 = this.snapshots_[selectedSnapshots[0]]; |
1505 var snapshot2 = this.snapshots_[selectedSnapshots[1]]; | 1510 var snapshot2 = this.snapshots_[selectedSnapshots[1]]; |
1506 | 1511 |
1507 var timeDeltaInSeconds = | 1512 var timeDeltaInSeconds = |
1508 ((snapshot2.time - snapshot1.time) / 1000).toFixed(0); | 1513 ((snapshot2.time - snapshot1.time) / 1000).toFixed(0); |
1509 | 1514 |
1510 // Explain that what is being shown is the difference between two | 1515 // Explain that what is being shown is the difference between two |
1511 // snapshots. | 1516 // snapshots. |
1512 summaryDiv.innerText = | 1517 summaryDiv.innerText = 'Showing the difference between snapshots #' + |
1513 'Showing the difference between snapshots #' + | 1518 selectedSnapshots[0] + ' and #' + selectedSnapshots[1] + ' (' + |
1514 selectedSnapshots[0] + ' and #' + | 1519 timeDeltaInSeconds + ' seconds worth of data)'; |
1515 selectedSnapshots[1] + ' (' + timeDeltaInSeconds + | |
1516 ' seconds worth of data)'; | |
1517 } else { | 1520 } else { |
1518 // This shouldn't be possible... | 1521 // This shouldn't be possible... |
1519 throw 'Unexpected number of selected snapshots'; | 1522 throw 'Unexpected number of selected snapshots'; |
1520 } | 1523 } |
1521 }, | 1524 }, |
1522 | 1525 |
1523 updateMergedData_: function() { | 1526 updateMergedData_: function() { |
1524 // Retrieve the merge options. | 1527 // Retrieve the merge options. |
1525 var mergeColumns = this.getMergeColumns_(); | 1528 var mergeColumns = this.getMergeColumns_(); |
1526 var shouldMergeSimilarThreads = this.shouldMergeSimilarThreads_(); | 1529 var shouldMergeSimilarThreads = this.shouldMergeSimilarThreads_(); |
1527 | 1530 |
1528 var selectedSnapshots = this.getSelectedSnapshotIndexes_(); | 1531 var selectedSnapshots = this.getSelectedSnapshotIndexes_(); |
1529 | 1532 |
1530 // We do merges a bit differently depending if we are displaying the diffs | 1533 // We do merges a bit differently depending if we are displaying the diffs |
1531 // between two snapshots, or just displaying a single snapshot. | 1534 // between two snapshots, or just displaying a single snapshot. |
1532 if (selectedSnapshots.length == 1) { | 1535 if (selectedSnapshots.length == 1) { |
1533 var snapshot = this.snapshots_[selectedSnapshots[0]]; | 1536 var snapshot = this.snapshots_[selectedSnapshots[0]]; |
1534 this.mergedData_ = mergeRows(snapshot.flatData, | 1537 this.mergedData_ = mergeRows( |
1535 mergeColumns, | 1538 snapshot.flatData, mergeColumns, shouldMergeSimilarThreads, false); |
1536 shouldMergeSimilarThreads, | |
1537 false); | |
1538 | 1539 |
1539 } else if (selectedSnapshots.length == 2) { | 1540 } else if (selectedSnapshots.length == 2) { |
1540 var snapshot1 = this.snapshots_[selectedSnapshots[0]]; | 1541 var snapshot1 = this.snapshots_[selectedSnapshots[0]]; |
1541 var snapshot2 = this.snapshots_[selectedSnapshots[1]]; | 1542 var snapshot2 = this.snapshots_[selectedSnapshots[1]]; |
1542 | 1543 |
1543 // Merge the data for snapshot1. | 1544 // Merge the data for snapshot1. |
1544 var mergedRows1 = mergeRows(snapshot1.flatData, | 1545 var mergedRows1 = mergeRows( |
1545 mergeColumns, | 1546 snapshot1.flatData, mergeColumns, shouldMergeSimilarThreads, true); |
1546 shouldMergeSimilarThreads, | |
1547 true); | |
1548 | 1547 |
1549 // Merge the data for snapshot2. | 1548 // Merge the data for snapshot2. |
1550 var mergedRows2 = mergeRows(snapshot2.flatData, | 1549 var mergedRows2 = mergeRows( |
1551 mergeColumns, | 1550 snapshot2.flatData, mergeColumns, shouldMergeSimilarThreads, true); |
1552 shouldMergeSimilarThreads, | |
1553 true); | |
1554 | 1551 |
1555 // Do a diff between the two snapshots. | 1552 // Do a diff between the two snapshots. |
1556 this.mergedData_ = subtractSnapshots(mergedRows1, | 1553 this.mergedData_ = |
1557 mergedRows2, | 1554 subtractSnapshots(mergedRows1, mergedRows2, mergeColumns); |
1558 mergeColumns); | |
1559 } else { | 1555 } else { |
1560 throw 'Unexpected number of selected snapshots'; | 1556 throw 'Unexpected number of selected snapshots'; |
1561 } | 1557 } |
1562 | 1558 |
1563 // Recompute filteredData_ (since it is derived from mergedData_) | 1559 // Recompute filteredData_ (since it is derived from mergedData_) |
1564 this.updateFilteredData_(); | 1560 this.updateFilteredData_(); |
1565 }, | 1561 }, |
1566 | 1562 |
1567 updateFilteredData_: function() { | 1563 updateFilteredData_: function() { |
1568 // Recompute filteredData_. | 1564 // Recompute filteredData_. |
(...skipping 147 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
1716 table.className = 'results-table'; | 1712 table.className = 'results-table'; |
1717 var thead = addNode(table, 'thead'); | 1713 var thead = addNode(table, 'thead'); |
1718 var tbody = addNode(table, 'tbody'); | 1714 var tbody = addNode(table, 'tbody'); |
1719 | 1715 |
1720 var displaySettings = this.getGroupDisplaySettings_(groupKey); | 1716 var displaySettings = this.getGroupDisplaySettings_(groupKey); |
1721 var limit = displaySettings.limit; | 1717 var limit = displaySettings.limit; |
1722 | 1718 |
1723 this.drawAggregateRow_(thead, data.aggregates, columns); | 1719 this.drawAggregateRow_(thead, data.aggregates, columns); |
1724 this.drawTableHeader_(thead, columns); | 1720 this.drawTableHeader_(thead, columns); |
1725 this.drawTableBody_(tbody, data.rows, columns, limit); | 1721 this.drawTableBody_(tbody, data.rows, columns, limit); |
1726 this.drawTruncationRow_(tbody, data.rows.length, limit, columns.length, | 1722 this.drawTruncationRow_( |
1727 groupKey); | 1723 tbody, data.rows.length, limit, columns.length, groupKey); |
1728 }, | 1724 }, |
1729 | 1725 |
1730 drawTableHeader_: function(thead, columns) { | 1726 drawTableHeader_: function(thead, columns) { |
1731 var tr = addNode(thead, 'tr'); | 1727 var tr = addNode(thead, 'tr'); |
1732 for (var i = 0; i < columns.length; ++i) { | 1728 for (var i = 0; i < columns.length; ++i) { |
1733 var key = columns[i]; | 1729 var key = columns[i]; |
1734 var th = addNode(tr, 'th', getNameForKey(key)); | 1730 var th = addNode(tr, 'th', getNameForKey(key)); |
1735 th.onclick = this.onClickColumn_.bind(this, key); | 1731 th.onclick = this.onClickColumn_.bind(this, key); |
1736 | 1732 |
1737 // Draw an indicator if we are currently sorted on this column. | 1733 // Draw an indicator if we are currently sorted on this column. |
(...skipping 194 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
1932 this.addSnapshotToList_(this.snapshots_.length - 1); | 1928 this.addSnapshotToList_(this.snapshots_.length - 1); |
1933 | 1929 |
1934 // Ask the browser for the profiling data. We will receive the data | 1930 // Ask the browser for the profiling data. We will receive the data |
1935 // later through a callback to addDataToSnapshot_(). | 1931 // later through a callback to addDataToSnapshot_(). |
1936 g_browserBridge.sendGetData(); | 1932 g_browserBridge.sendGetData(); |
1937 }, | 1933 }, |
1938 | 1934 |
1939 saveSnapshots_: function() { | 1935 saveSnapshots_: function() { |
1940 var snapshots = []; | 1936 var snapshots = []; |
1941 for (var i = 0; i < this.snapshots_.length; ++i) { | 1937 for (var i = 0; i < this.snapshots_.length; ++i) { |
1942 snapshots.push({ data: this.snapshots_[i].origData, | 1938 snapshots.push({ |
1943 timestamp: Math.floor( | 1939 data: this.snapshots_[i].origData, |
1944 this.snapshots_[i].time / 1000) }); | 1940 timestamp: Math.floor(this.snapshots_[i].time / 1000) |
| 1941 }); |
1945 } | 1942 } |
1946 | 1943 |
1947 var dump = { | 1944 var dump = { |
1948 'userAgent': navigator.userAgent, | 1945 'userAgent': navigator.userAgent, |
1949 'version': 1, | 1946 'version': 1, |
1950 'snapshots': snapshots | 1947 'snapshots': snapshots |
1951 }; | 1948 }; |
1952 | 1949 |
1953 var dumpText = JSON.stringify(dump, null, ' '); | 1950 var dumpText = JSON.stringify(dump, null, ' '); |
1954 var textBlob = new Blob([dumpText], | 1951 var textBlob = |
1955 { type: 'octet/stream', endings: 'native' }); | 1952 new Blob([dumpText], {type: 'octet/stream', endings: 'native'}); |
1956 var blobUrl = window.URL.createObjectURL(textBlob); | 1953 var blobUrl = window.URL.createObjectURL(textBlob); |
1957 $(DOWNLOAD_ANCHOR_ID).href = blobUrl; | 1954 $(DOWNLOAD_ANCHOR_ID).href = blobUrl; |
1958 $(DOWNLOAD_ANCHOR_ID).click(); | 1955 $(DOWNLOAD_ANCHOR_ID).click(); |
1959 }, | 1956 }, |
1960 | 1957 |
1961 loadFileChanged_: function() { | 1958 loadFileChanged_: function() { |
1962 this.loadSnapshots_($(SNAPSHOT_FILE_LOADER_ID).files[0]); | 1959 this.loadSnapshots_($(SNAPSHOT_FILE_LOADER_ID).files[0]); |
1963 }, | 1960 }, |
1964 | 1961 |
1965 loadSnapshots_: function(file) { | 1962 loadSnapshots_: function(file) { |
(...skipping 38 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
2004 this.clearExistingSnapshots_(); | 2001 this.clearExistingSnapshots_(); |
2005 $(TAKE_SNAPSHOT_BUTTON_ID).disabled = true; | 2002 $(TAKE_SNAPSHOT_BUTTON_ID).disabled = true; |
2006 $(SAVE_SNAPSHOTS_BUTTON_ID).disabled = true; | 2003 $(SAVE_SNAPSHOTS_BUTTON_ID).disabled = true; |
2007 | 2004 |
2008 if (content.snapshots.length > 1) { | 2005 if (content.snapshots.length > 1) { |
2009 setNodeDisplay($(SNAPSHOTS_ROW), true); | 2006 setNodeDisplay($(SNAPSHOTS_ROW), true); |
2010 } | 2007 } |
2011 | 2008 |
2012 for (var i = 0; i < content.snapshots.length; ++i) { | 2009 for (var i = 0; i < content.snapshots.length; ++i) { |
2013 var snapshot = content.snapshots[i]; | 2010 var snapshot = content.snapshots[i]; |
2014 this.snapshots_.push({flatData: [], origData: [], | 2011 this.snapshots_.push( |
2015 time: snapshot.timestamp * 1000}); | 2012 {flatData: [], origData: [], time: snapshot.timestamp * 1000}); |
2016 this.addSnapshotToList_(this.snapshots_.length - 1); | 2013 this.addSnapshotToList_(this.snapshots_.length - 1); |
2017 var snapshotData = snapshot.data; | 2014 var snapshotData = snapshot.data; |
2018 for (var j = 0; j < snapshotData.length; ++j) { | 2015 for (var j = 0; j < snapshotData.length; ++j) { |
2019 this.addDataToSnapshot(snapshotData[j]); | 2016 this.addDataToSnapshot(snapshotData[j]); |
2020 } | 2017 } |
2021 } | 2018 } |
2022 this.redrawData_(); | 2019 this.redrawData_(); |
2023 }, | 2020 }, |
2024 | 2021 |
2025 onLoadSnapshotsFileError_: function(file, filedata) { | 2022 onLoadSnapshotsFileError_: function(file, filedata) { |
(...skipping 59 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
2085 | 2082 |
2086 onSnapshotCheckboxChanged_: function(event) { | 2083 onSnapshotCheckboxChanged_: function(event) { |
2087 // Keep track of when we clicked this box (for when we need to uncheck | 2084 // Keep track of when we clicked this box (for when we need to uncheck |
2088 // older boxes). | 2085 // older boxes). |
2089 event.target.__time = getTimeMillis(); | 2086 event.target.__time = getTimeMillis(); |
2090 | 2087 |
2091 // Find all the checked boxes. Either 1 or 2 can be checked. If a third | 2088 // Find all the checked boxes. Either 1 or 2 can be checked. If a third |
2092 // was just checked, then uncheck one of the earlier ones so we only have | 2089 // was just checked, then uncheck one of the earlier ones so we only have |
2093 // 2. | 2090 // 2. |
2094 var checked = this.getSelectedSnapshotBoxes_(); | 2091 var checked = this.getSelectedSnapshotBoxes_(); |
2095 checked.sort(function(a, b) { return b.__time - a.__time; }); | 2092 checked.sort(function(a, b) { |
| 2093 return b.__time - a.__time; |
| 2094 }); |
2096 if (checked.length > 2) { | 2095 if (checked.length > 2) { |
2097 for (var i = 2; i < checked.length; ++i) | 2096 for (var i = 2; i < checked.length; ++i) |
2098 checked[i].checked = false; | 2097 checked[i].checked = false; |
2099 checked.length = 2; | 2098 checked.length = 2; |
2100 } | 2099 } |
2101 | 2100 |
2102 // We should always have at least 1 selection. Prevent the user from | 2101 // We should always have at least 1 selection. Prevent the user from |
2103 // unselecting the final box. | 2102 // unselecting the final box. |
2104 if (checked.length == 0) | 2103 if (checked.length == 0) |
2105 event.target.checked = true; | 2104 event.target.checked = true; |
(...skipping 197 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
2303 }; | 2302 }; |
2304 }, | 2303 }, |
2305 | 2304 |
2306 getGroupSortingFunction_: function() { | 2305 getGroupSortingFunction_: function() { |
2307 return function(a, b) { | 2306 return function(a, b) { |
2308 var groupKey1 = JSON.parse(a); | 2307 var groupKey1 = JSON.parse(a); |
2309 var groupKey2 = JSON.parse(b); | 2308 var groupKey2 = JSON.parse(b); |
2310 | 2309 |
2311 for (var i = 0; i < groupKey1.length; ++i) { | 2310 for (var i = 0; i < groupKey1.length; ++i) { |
2312 var comparison = compareValuesForKey( | 2311 var comparison = compareValuesForKey( |
2313 groupKey1[i].key, | 2312 groupKey1[i].key, groupKey1[i].value, groupKey2[i].value); |
2314 groupKey1[i].value, | |
2315 groupKey2[i].value); | |
2316 | 2313 |
2317 if (comparison != 0) | 2314 if (comparison != 0) |
2318 return comparison; | 2315 return comparison; |
2319 } | 2316 } |
2320 | 2317 |
2321 // Tie breaker. | 2318 // Tie breaker. |
2322 return simpleCompare(a, b); | 2319 return simpleCompare(a, b); |
2323 }; | 2320 }; |
2324 }, | 2321 }, |
2325 | 2322 |
(...skipping 28 matching lines...) Expand all Loading... |
2354 deleteValuesFromArray(groupings, ['']); | 2351 deleteValuesFromArray(groupings, ['']); |
2355 | 2352 |
2356 // Eliminate duplicate primary/secondary group by directives, since they | 2353 // Eliminate duplicate primary/secondary group by directives, since they |
2357 // are redundant. | 2354 // are redundant. |
2358 deleteDuplicateStringsFromArray(groupings); | 2355 deleteDuplicateStringsFromArray(groupings); |
2359 | 2356 |
2360 return function(e) { | 2357 return function(e) { |
2361 var groupKey = []; | 2358 var groupKey = []; |
2362 | 2359 |
2363 for (var i = 0; i < groupings.length; ++i) { | 2360 for (var i = 0; i < groupings.length; ++i) { |
2364 var entry = {key: groupings[i], | 2361 var entry = {key: groupings[i], value: e[groupings[i]]}; |
2365 value: e[groupings[i]]}; | |
2366 groupKey.push(entry); | 2362 groupKey.push(entry); |
2367 } | 2363 } |
2368 | 2364 |
2369 return JSON.stringify(groupKey); | 2365 return JSON.stringify(groupKey); |
2370 }; | 2366 }; |
2371 }, | 2367 }, |
2372 }; | 2368 }; |
2373 | 2369 |
2374 return MainView; | 2370 return MainView; |
2375 })(); | 2371 })(); |
OLD | NEW |