OLD | NEW |
1 /* | 1 /* |
2 * Copyright (C) 2011 Google Inc. All rights reserved. | 2 * Copyright (C) 2011 Google Inc. All rights reserved. |
3 * | 3 * |
4 * Redistribution and use in source and binary forms, with or without | 4 * Redistribution and use in source and binary forms, with or without |
5 * modification, are permitted provided that the following conditions are | 5 * modification, are permitted provided that the following conditions are |
6 * met: | 6 * met: |
7 * | 7 * |
8 * * Redistributions of source code must retain the above copyright | 8 * * Redistributions of source code must retain the above copyright |
9 * notice, this list of conditions and the following disclaimer. | 9 * notice, this list of conditions and the following disclaimer. |
10 * * Redistributions in binary form must reproduce the above | 10 * * Redistributions in binary form must reproduce the above |
(...skipping 757 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
768 * @extends {WebInspector.ProfileType} | 768 * @extends {WebInspector.ProfileType} |
769 * @implements {HeapProfilerAgent.Dispatcher} | 769 * @implements {HeapProfilerAgent.Dispatcher} |
770 */ | 770 */ |
771 WebInspector.HeapSnapshotProfileType = function() | 771 WebInspector.HeapSnapshotProfileType = function() |
772 { | 772 { |
773 WebInspector.ProfileType.call(this, WebInspector.HeapSnapshotProfileType.Typ
eId, WebInspector.UIString("Take Heap Snapshot")); | 773 WebInspector.ProfileType.call(this, WebInspector.HeapSnapshotProfileType.Typ
eId, WebInspector.UIString("Take Heap Snapshot")); |
774 InspectorBackend.registerHeapProfilerDispatcher(this); | 774 InspectorBackend.registerHeapProfilerDispatcher(this); |
775 } | 775 } |
776 | 776 |
777 WebInspector.HeapSnapshotProfileType.TypeId = "HEAP"; | 777 WebInspector.HeapSnapshotProfileType.TypeId = "HEAP"; |
| 778 WebInspector.HeapSnapshotProfileType.HeapStatsUpdate = "HeapStatsUpdate"; |
778 | 779 |
779 WebInspector.HeapSnapshotProfileType.prototype = { | 780 WebInspector.HeapSnapshotProfileType.prototype = { |
780 /** | 781 /** |
781 * @override | 782 * @override |
782 * @return {string} | 783 * @return {string} |
783 */ | 784 */ |
784 fileExtension: function() | 785 fileExtension: function() |
785 { | 786 { |
786 return ".heapsnapshot"; | 787 return ".heapsnapshot"; |
787 }, | 788 }, |
(...skipping 75 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
863 this._lastUpdatedIndex = index; | 864 this._lastUpdatedIndex = index; |
864 }, | 865 }, |
865 | 866 |
866 /** | 867 /** |
867 * @override | 868 * @override |
868 * @param {number} lastSeenObjectId | 869 * @param {number} lastSeenObjectId |
869 * @param {number} timestamp | 870 * @param {number} timestamp |
870 */ | 871 */ |
871 lastSeenObjectId: function(lastSeenObjectId, timestamp) | 872 lastSeenObjectId: function(lastSeenObjectId, timestamp) |
872 { | 873 { |
| 874 if (!this._profileSamples) |
| 875 return; |
| 876 |
873 this._profileSamples.ids[this._currentIndex] = lastSeenObjectId; | 877 this._profileSamples.ids[this._currentIndex] = lastSeenObjectId; |
874 this._profileSamples.timestamps[this._currentIndex] = timestamp; | 878 this._profileSamples.timestamps[this._currentIndex] = timestamp; |
875 if (!this._profileSamples.max[this._currentIndex]) { | 879 if (!this._profileSamples.max[this._currentIndex]) { |
876 this._profileSamples.max[this._currentIndex] = 0; | 880 this._profileSamples.max[this._currentIndex] = 0; |
877 this._profileSamples.sizes[this._currentIndex] = 0; | 881 this._profileSamples.sizes[this._currentIndex] = 0; |
878 } | 882 } |
879 ++this._currentIndex; | 883 ++this._currentIndex; |
| 884 this.dispatchEventToListeners(WebInspector.HeapSnapshotProfileType.HeapS
tatsUpdate, this._profileSamples); |
880 }, | 885 }, |
881 | 886 |
882 get treeItemTitle() | 887 get treeItemTitle() |
883 { | 888 { |
884 return WebInspector.UIString("HEAP SNAPSHOTS"); | 889 return WebInspector.UIString("HEAP SNAPSHOTS"); |
885 }, | 890 }, |
886 | 891 |
887 get description() | 892 get description() |
888 { | 893 { |
889 return WebInspector.UIString("Heap snapshot profiles show memory distrib
ution among your page's JavaScript objects and related DOM nodes."); | 894 return WebInspector.UIString("Heap snapshot profiles show memory distrib
ution among your page's JavaScript objects and related DOM nodes."); |
(...skipping 116 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
1006 WebInspector.TrackingHeapSnapshotProfileType = function(profilesPanel, profileTy
pe) | 1011 WebInspector.TrackingHeapSnapshotProfileType = function(profilesPanel, profileTy
pe) |
1007 { | 1012 { |
1008 WebInspector.ProfileType.call(this, WebInspector.TrackingHeapSnapshotProfile
Type.TypeId, WebInspector.UIString("Track Allocations")); | 1013 WebInspector.ProfileType.call(this, WebInspector.TrackingHeapSnapshotProfile
Type.TypeId, WebInspector.UIString("Track Allocations")); |
1009 this._profilesPanel = profilesPanel; | 1014 this._profilesPanel = profilesPanel; |
1010 this._parentType = profileType; | 1015 this._parentType = profileType; |
1011 } | 1016 } |
1012 | 1017 |
1013 WebInspector.TrackingHeapSnapshotProfileType.TypeId = "HEAP-RECORD"; | 1018 WebInspector.TrackingHeapSnapshotProfileType.TypeId = "HEAP-RECORD"; |
1014 | 1019 |
1015 WebInspector.TrackingHeapSnapshotProfileType.prototype = { | 1020 WebInspector.TrackingHeapSnapshotProfileType.prototype = { |
| 1021 hasTemporaryView: function() |
| 1022 { |
| 1023 return true; |
| 1024 }, |
| 1025 |
1016 get buttonTooltip() | 1026 get buttonTooltip() |
1017 { | 1027 { |
1018 return this._recording ? WebInspector.UIString("Stop recording heap prof
ile.") : WebInspector.UIString("Start recording heap profile."); | 1028 return this._recording ? WebInspector.UIString("Stop recording heap prof
ile.") : WebInspector.UIString("Start recording heap profile."); |
1019 }, | 1029 }, |
1020 | 1030 |
1021 /** | 1031 /** |
1022 * @override | 1032 * @override |
1023 * @return {boolean} | 1033 * @return {boolean} |
1024 */ | 1034 */ |
1025 isInstantProfile: function() | 1035 isInstantProfile: function() |
(...skipping 77 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
1103 { | 1113 { |
1104 return new WebInspector.ProfileSidebarTreeElement(this, WebInspector.UIS
tring("Snapshot %d"), "heap-snapshot-sidebar-tree-item"); | 1114 return new WebInspector.ProfileSidebarTreeElement(this, WebInspector.UIS
tring("Snapshot %d"), "heap-snapshot-sidebar-tree-item"); |
1105 }, | 1115 }, |
1106 | 1116 |
1107 /** | 1117 /** |
1108 * @override | 1118 * @override |
1109 * @param {!WebInspector.ProfilesPanel} profilesPanel | 1119 * @param {!WebInspector.ProfilesPanel} profilesPanel |
1110 */ | 1120 */ |
1111 createView: function(profilesPanel) | 1121 createView: function(profilesPanel) |
1112 { | 1122 { |
| 1123 if (this._profileType.id === WebInspector.TrackingHeapSnapshotProfileTyp
e.TypeId) { |
| 1124 var view = new WebInspector.HeapTrackingOverviewGrid(this); |
| 1125 this._profileType._parentType.addEventListener(WebInspector.HeapSnap
shotProfileType.HeapStatsUpdate, view._onHeapStatsUpdate.bind(view)); |
| 1126 return view; |
| 1127 } |
1113 return new WebInspector.HeapSnapshotView(profilesPanel, this); | 1128 return new WebInspector.HeapSnapshotView(profilesPanel, this); |
1114 }, | 1129 }, |
1115 | 1130 |
1116 /** | 1131 /** |
1117 * @override | 1132 * @override |
1118 * @param {function(WebInspector.HeapSnapshotProxy):void} callback | 1133 * @param {function(WebInspector.HeapSnapshotProxy):void} callback |
1119 */ | 1134 */ |
1120 load: function(callback) | 1135 load: function(callback) |
1121 { | 1136 { |
1122 if (this._snapshotProxy) { | 1137 if (this._snapshotProxy) { |
(...skipping 207 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
1330 break; | 1345 break; |
1331 default: | 1346 default: |
1332 this._snapshotHeader.sidebarElement.subtitle = WebInspector.UIString
("'%s' error %d", reader.fileName(), e.target.error.code); | 1347 this._snapshotHeader.sidebarElement.subtitle = WebInspector.UIString
("'%s' error %d", reader.fileName(), e.target.error.code); |
1333 } | 1348 } |
1334 } | 1349 } |
1335 } | 1350 } |
1336 | 1351 |
1337 /** | 1352 /** |
1338 * @constructor | 1353 * @constructor |
1339 * @extends {WebInspector.View} | 1354 * @extends {WebInspector.View} |
1340 * @param {!WebInspector.HeapProfileHeader} heapProfileHeader | 1355 * @param {?WebInspector.HeapProfileHeader} heapProfileHeader |
1341 */ | 1356 */ |
1342 WebInspector.HeapTrackingOverviewGrid = function(heapProfileHeader) | 1357 WebInspector.HeapTrackingOverviewGrid = function(heapProfileHeader) |
1343 { | 1358 { |
1344 WebInspector.View.call(this); | 1359 WebInspector.View.call(this); |
1345 this.registerRequiredCSS("flameChart.css"); | 1360 this.registerRequiredCSS("flameChart.css"); |
1346 this.element.id = "heap-recording-view"; | 1361 this.element.id = "heap-recording-view"; |
1347 | 1362 |
1348 this._overviewContainer = this.element.createChild("div", "overview-containe
r"); | 1363 this._overviewContainer = this.element.createChild("div", "overview-containe
r"); |
1349 this._overviewGrid = new WebInspector.OverviewGrid("heap-recording"); | 1364 this._overviewGrid = new WebInspector.OverviewGrid("heap-recording"); |
1350 this._overviewCanvas = this._overviewContainer.createChild("canvas", "heap-r
ecording-overview-canvas"); | 1365 this._overviewCanvas = this._overviewContainer.createChild("canvas", "heap-r
ecording-overview-canvas"); |
1351 this._overviewContainer.appendChild(this._overviewGrid.element); | 1366 this._overviewContainer.appendChild(this._overviewGrid.element); |
1352 this._overviewCalculator = new WebInspector.HeapTrackingOverviewGrid.Overvie
wCalculator(); | 1367 this._overviewCalculator = new WebInspector.HeapTrackingOverviewGrid.Overvie
wCalculator(); |
1353 this._overviewGrid.addEventListener(WebInspector.OverviewGrid.Events.WindowC
hanged, this._onWindowChanged, this); | 1368 this._overviewGrid.addEventListener(WebInspector.OverviewGrid.Events.WindowC
hanged, this._onWindowChanged, this); |
1354 | 1369 |
1355 this._profileSamples = heapProfileHeader._profileSamples; | 1370 this._minimumTimeDelta = 60000; |
1356 var timestamps = this._profileSamples.timestamps; | 1371 if (heapProfileHeader && heapProfileHeader._profileSamples) { |
1357 var startTime = timestamps[0]; | 1372 this._profileSamples = heapProfileHeader._profileSamples; |
1358 this._totalTime = timestamps[timestamps.length - 1] - startTime; | 1373 var timestamps = this._profileSamples.timestamps; |
| 1374 var startTime = timestamps[0]; |
| 1375 this._totalTime = timestamps[timestamps.length - 1] - startTime; |
| 1376 } else |
| 1377 this._resetTrackingData(); |
1359 this._windowLeft = 0.0; | 1378 this._windowLeft = 0.0; |
1360 this._windowRight = 1.0; | 1379 this._windowRight = 1.0; |
1361 } | 1380 } |
1362 | 1381 |
1363 WebInspector.HeapTrackingOverviewGrid.IdsRangeChanged = "IdsRangeChanged"; | 1382 WebInspector.HeapTrackingOverviewGrid.IdsRangeChanged = "IdsRangeChanged"; |
1364 | 1383 |
1365 WebInspector.HeapTrackingOverviewGrid.prototype = { | 1384 WebInspector.HeapTrackingOverviewGrid.prototype = { |
| 1385 _resetTrackingData: function(profileSamples) |
| 1386 { |
| 1387 this._totalTime = this._minimumTimeDelta; |
| 1388 this._profileSamples = profileSamples; |
| 1389 }, |
| 1390 |
1366 /** | 1391 /** |
1367 * @param {number} width | 1392 * @param {number} width |
1368 * @param {number} height | 1393 * @param {number} height |
1369 */ | 1394 */ |
1370 _drawOverviewCanvas: function(width, height) | 1395 _drawOverviewCanvas: function(width, height) |
1371 { | 1396 { |
| 1397 if (!this._profileSamples) |
| 1398 return; |
1372 var sizes = this._profileSamples.sizes; | 1399 var sizes = this._profileSamples.sizes; |
1373 var usedSizes = this._profileSamples.max; | 1400 var usedSizes = this._profileSamples.max; |
1374 var timestamps = this._profileSamples.timestamps; | 1401 var timestamps = this._profileSamples.timestamps; |
1375 | 1402 |
1376 var scaleFactor = width / this._totalTime; | 1403 var scaleFactor = width / this._totalTime; |
1377 var maxUsedSize = 0; | 1404 var maxUsedSize = 0; |
1378 var currentX = 0; | 1405 var currentX = 0; |
1379 /** | 1406 /** |
1380 * @param {Array.<number>} sizes | 1407 * @param {Array.<number>} sizes |
1381 * @param {function(number, number):void} callback | 1408 * @param {function(number, number):void} callback |
1382 */ | 1409 */ |
1383 function aggregateAndCall(sizes, callback) | 1410 function aggregateAndCall(sizes, callback) |
1384 { | 1411 { |
1385 var size = 0; | 1412 var size = 0; |
1386 var currentX = 0; | 1413 var currentX = 0; |
1387 for (var i = 1; i < timestamps.length; ++i) { | 1414 for (var i = 1; i < timestamps.length; ++i) { |
1388 var x = Math.floor((timestamps[i] - startTime) * scaleFactor) ; | 1415 var x = Math.floor((timestamps[i] - startTime) * scaleFactor); |
1389 if (x !== currentX) { | 1416 if (x !== currentX) { |
1390 if (size) | 1417 if (size) |
1391 callback(currentX, size); | 1418 callback(currentX, size); |
1392 size = 0; | 1419 size = 0; |
1393 currentX = x; | 1420 currentX = x; |
1394 } | 1421 } |
1395 size += sizes[i]; | 1422 size += sizes[i]; |
1396 } | 1423 } |
1397 callback(currentX, size); | 1424 callback(currentX, size); |
1398 } | 1425 } |
1399 | 1426 |
1400 /** | 1427 /** |
1401 * @param {number} x | 1428 * @param {number} x |
1402 * @param {number} size | 1429 * @param {number} size |
1403 */ | 1430 */ |
1404 function maxUsedSizeCallback(x, size) | 1431 function maxUsedSizeCallback(x, size) |
1405 { | 1432 { |
1406 maxUsedSize = Math.max(maxUsedSize, size); | 1433 maxUsedSize = Math.max(maxUsedSize, size); |
1407 } | 1434 } |
1408 | 1435 |
1409 aggregateAndCall(usedSizes, maxUsedSizeCallback); | 1436 aggregateAndCall(usedSizes, maxUsedSizeCallback); |
1410 | 1437 |
1411 this._overviewCanvas.width = width * window.devicePixelRatio; | 1438 this._overviewCanvas.width = width * window.devicePixelRatio; |
1412 this._overviewCanvas.height = height * window.devicePixelRatio; | 1439 this._overviewCanvas.height = height * window.devicePixelRatio; |
1413 this._overviewCanvas.style.width = width + "px"; | 1440 this._overviewCanvas.style.width = width + "px"; |
1414 this._overviewCanvas.style.height = height + "px"; | 1441 this._overviewCanvas.style.height = height + "px"; |
1415 var yScaleFactor = height / (maxUsedSize * 1.1); | 1442 var yScaleFactor = height / (maxUsedSize * 1.1); |
1416 var startTime = timestamps[0]; | 1443 var startTime = timestamps[0]; |
| 1444 var endTime = timestamps[timestamps.length - 1]; |
1417 | 1445 |
1418 var context = this._overviewCanvas.getContext("2d"); | 1446 var context = this._overviewCanvas.getContext("2d"); |
1419 context.scale(window.devicePixelRatio, window.devicePixelRatio); | 1447 context.scale(window.devicePixelRatio, window.devicePixelRatio); |
1420 | 1448 |
| 1449 context.beginPath(); |
| 1450 context.lineWidth = 2; |
| 1451 context.strokeStyle = "rgba(192, 192, 192, 0.6)"; |
| 1452 var currentX = Math.floor((endTime - startTime) * scaleFactor); |
| 1453 context.moveTo(currentX, height - 1); |
| 1454 context.lineTo(currentX, 0); |
| 1455 context.stroke(); |
| 1456 context.closePath(); |
| 1457 |
1421 /** | 1458 /** |
1422 * @param {number} x | 1459 * @param {number} x |
1423 * @param {number} size | 1460 * @param {number} size |
1424 */ | 1461 */ |
1425 function drawBarCallback(x, size) | 1462 function drawBarCallback(x, size) |
1426 { | 1463 { |
1427 context.moveTo(x, height - 1); | 1464 context.moveTo(x, height - 1); |
1428 context.lineTo(x, Math.round(height - size * yScaleFactor - 1)); | 1465 context.lineTo(x, Math.round(height - size * yScaleFactor - 1)); |
1429 } | 1466 } |
1430 | 1467 |
(...skipping 17 matching lines...) Expand all Loading... |
1448 this._updateOverviewCanvas = true; | 1485 this._updateOverviewCanvas = true; |
1449 this._scheduleUpdate(); | 1486 this._scheduleUpdate(); |
1450 }, | 1487 }, |
1451 | 1488 |
1452 _onWindowChanged: function() | 1489 _onWindowChanged: function() |
1453 { | 1490 { |
1454 if (!this._updateGridTimerId) | 1491 if (!this._updateGridTimerId) |
1455 this._updateGridTimerId = setTimeout(this._updateGrid.bind(this), 10
); | 1492 this._updateGridTimerId = setTimeout(this._updateGrid.bind(this), 10
); |
1456 }, | 1493 }, |
1457 | 1494 |
| 1495 _onHeapStatsUpdate: function(event) |
| 1496 { |
| 1497 this._profileSamples = event.data; |
| 1498 var timestamps = this._profileSamples.timestamps; |
| 1499 if (this._totalTime < timestamps[timestamps.length - 1] - timestamps[0]) |
| 1500 this._totalTime *= 2; |
| 1501 this._scheduleUpdate(); |
| 1502 }, |
| 1503 |
1458 _scheduleUpdate: function() | 1504 _scheduleUpdate: function() |
1459 { | 1505 { |
1460 if (this._updateTimerId) | 1506 if (this._updateTimerId) |
1461 return; | 1507 return; |
1462 this._updateTimerId = setTimeout(this.update.bind(this), 10); | 1508 this._updateTimerId = setTimeout(this.update.bind(this), 10); |
1463 }, | 1509 }, |
1464 | 1510 |
1465 _updateBoundaries: function() | 1511 _updateBoundaries: function() |
1466 { | 1512 { |
1467 this._windowLeft = this._overviewGrid.windowLeft(); | 1513 this._windowLeft = this._overviewGrid.windowLeft(); |
1468 this._windowRight = this._overviewGrid.windowRight(); | 1514 this._windowRight = this._overviewGrid.windowRight(); |
1469 this._windowWidth = this._windowRight - this._windowLeft; | 1515 this._windowWidth = this._windowRight - this._windowLeft; |
1470 }, | 1516 }, |
1471 | 1517 |
1472 /** | 1518 /** |
1473 * @param {boolean} updateOverviewCanvas | 1519 * @param {boolean} updateOverviewCanvas |
1474 */ | 1520 */ |
1475 update: function(updateOverviewCanvas) | 1521 update: function(updateOverviewCanvas) |
1476 { | 1522 { |
1477 this._updateTimerId = null; | 1523 this._updateTimerId = null; |
1478 this._updateBoundaries(); | 1524 this._updateBoundaries(); |
1479 this._overviewCalculator._updateBoundaries(this); | 1525 this._overviewCalculator._updateBoundaries(this); |
1480 this._overviewGrid.updateDividers(this._overviewCalculator); | 1526 this._overviewGrid.updateDividers(this._overviewCalculator); |
1481 if (this._updateOverviewCanvas || updateOverviewCanvas) { | 1527 this._drawOverviewCanvas(this._overviewContainer.clientWidth, this._over
viewContainer.clientHeight - 20); |
1482 this._drawOverviewCanvas(this._overviewContainer.clientWidth, this._
overviewContainer.clientHeight - 20); | |
1483 this._updateOverviewCanvas = false; | |
1484 } | |
1485 }, | 1528 }, |
1486 | 1529 |
1487 _updateGrid: function() | 1530 _updateGrid: function() |
1488 { | 1531 { |
| 1532 if (!this._profileSamples) |
| 1533 return; |
1489 this._updateGridTimerId = 0; | 1534 this._updateGridTimerId = 0; |
1490 this._updateBoundaries(); | 1535 this._updateBoundaries(); |
1491 var ids = this._profileSamples.ids; | 1536 var ids = this._profileSamples.ids; |
1492 var timestamps = this._profileSamples.timestamps; | 1537 var timestamps = this._profileSamples.timestamps; |
1493 var sizes = this._profileSamples.sizes; | 1538 var sizes = this._profileSamples.sizes; |
1494 var startTime = timestamps[0]; | 1539 var startTime = timestamps[0]; |
1495 var finishTime = timestamps[timestamps.length - 1]; | 1540 var finishTime = timestamps[timestamps.length - 1]; |
1496 var timeRange = finishTime - startTime; | 1541 var timeRange = finishTime - startTime; |
1497 var timeLeft = startTime + timeRange * this._windowLeft; | 1542 var timeLeft = startTime + timeRange * this._windowLeft; |
1498 var timeRight = startTime + timeRange * this._windowRight; | 1543 var timeRight = startTime + timeRange * this._windowRight; |
(...skipping 65 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
1564 zeroTime: function() | 1609 zeroTime: function() |
1565 { | 1610 { |
1566 return this._minimumBoundaries; | 1611 return this._minimumBoundaries; |
1567 }, | 1612 }, |
1568 | 1613 |
1569 boundarySpan: function() | 1614 boundarySpan: function() |
1570 { | 1615 { |
1571 return this._maximumBoundaries - this._minimumBoundaries; | 1616 return this._maximumBoundaries - this._minimumBoundaries; |
1572 } | 1617 } |
1573 } | 1618 } |
OLD | NEW |