test_HeapSnapshot_takeCensus_11.js (4105B)
1 /* Any copyright is dedicated to the Public Domain. 2 http://creativecommons.org/publicdomain/zero/1.0/ */ 3 "use strict"; 4 5 // Test that Debugger.Memory.prototype.takeCensus and 6 // HeapSnapshot.prototype.takeCensus return the same data for the same heap 7 // graph. 8 9 function doLiveAndOfflineCensus(g, dbg, opts) { 10 dbg.memory.allocationSamplingProbability = 1; 11 dbg.memory.trackingAllocationSites = true; 12 g.eval(` // 1 13 (function unsafeAtAnySpeed() { // 2 14 for (var i = 0; i < 100; i++) { // 3 15 this.markers.push(allocationMarker()); // 4 16 } // 5 17 }()); // 6 18 `); 19 dbg.memory.trackingAllocationSites = false; 20 21 return { 22 live: dbg.memory.takeCensus(opts), 23 offline: saveHeapSnapshotAndTakeCensus(dbg, opts), 24 }; 25 } 26 27 function getMarkerSize(g, dbg) { 28 dbg.memory.allocationSamplingProbability = 1; 29 dbg.memory.trackingAllocationSites = true; 30 g.eval("var hold = allocationMarker();"); 31 dbg.memory.trackingAllocationSites = false; 32 const live = dbg.memory.takeCensus({ 33 breakdown: { by: "objectClass", then: { by: "count" } }, 34 }); 35 g.hold = null; 36 equal(live.AllocationMarker.count, 1); 37 return live.AllocationMarker.bytes; 38 } 39 40 function run_test() { 41 const g = newGlobal(); 42 const dbg = new Debugger(g); 43 44 g.eval("this.markers = []"); 45 const markerSize = getMarkerSize(g, dbg); 46 47 // First, test that we get the same counts and sizes as we allocate and retain 48 // more things. 49 50 let prevCount = 0; 51 let prevBytes = 0; 52 53 for (let i = 0; i < 10; i++) { 54 const { live, offline } = doLiveAndOfflineCensus(g, dbg, { 55 breakdown: { by: "objectClass", then: { by: "count" } }, 56 }); 57 58 equal(live.AllocationMarker.count, offline.AllocationMarker.count); 59 equal(live.AllocationMarker.bytes, offline.AllocationMarker.bytes); 60 equal(live.AllocationMarker.count, prevCount + 100); 61 equal(live.AllocationMarker.bytes, prevBytes + 100 * markerSize); 62 63 prevCount = live.AllocationMarker.count; 64 prevBytes = live.AllocationMarker.bytes; 65 } 66 67 // Second, test that the reported allocation stacks and counts and sizes at 68 // those allocation stacks match up. 69 70 const { live, offline } = doLiveAndOfflineCensus(g, dbg, { 71 breakdown: { by: "objectClass", then: { by: "allocationStack" } }, 72 }); 73 74 equal(live.AllocationMarker.size, offline.AllocationMarker.size); 75 // One stack with the loop further above, and another stack featuring the call 76 // right above. 77 equal(live.AllocationMarker.size, 2); 78 79 // Note that because SavedFrame stacks reconstructed from an offline heap 80 // snapshot don't have the same principals as SavedFrame stacks captured from 81 // a live stack, the live and offline allocation stacks won't be identity 82 // equal, but should be structurally the same. 83 84 const liveEntries = []; 85 live.AllocationMarker.forEach((v, k) => { 86 dumpn("Allocation stack:"); 87 k.toString() 88 .split(/\n/g) 89 .forEach(s => dumpn(s)); 90 91 equal(k.functionDisplayName, "unsafeAtAnySpeed"); 92 equal(k.line, 4); 93 94 liveEntries.push([k.toString(), v]); 95 }); 96 97 const offlineEntries = []; 98 offline.AllocationMarker.forEach((v, k) => { 99 dumpn("Allocation stack:"); 100 k.toString() 101 .split(/\n/g) 102 .forEach(s => dumpn(s)); 103 104 equal(k.functionDisplayName, "unsafeAtAnySpeed"); 105 equal(k.line, 4); 106 107 offlineEntries.push([k.toString(), v]); 108 }); 109 110 const sortEntries = (a, b) => { 111 if (a[0] < b[0]) { 112 return -1; 113 } else if (a[0] > b[0]) { 114 return 1; 115 } 116 return 0; 117 }; 118 liveEntries.sort(sortEntries); 119 offlineEntries.sort(sortEntries); 120 121 equal(liveEntries.length, live.AllocationMarker.size); 122 equal(liveEntries.length, offlineEntries.length); 123 124 for (let i = 0; i < liveEntries.length; i++) { 125 equal(liveEntries[i][0], offlineEntries[i][0]); 126 equal(liveEntries[i][1].count, offlineEntries[i][1].count); 127 equal(liveEntries[i][1].bytes, offlineEntries[i][1].bytes); 128 } 129 130 do_test_finished(); 131 }