@@ -17,19 +17,22 @@ import {
17
17
var active_plot = null ;
18
18
var current_dimensions = null ;
19
19
20
- var parent_index_by_child_index = ( function ( ) {
21
- let ret = new Array ( packed_data . nodes . children . length ) ;
20
+ var parent_index_by_child_index = generateParentIndexes ( packed_data . nodes ) ;
21
+ var inverted_no_imports_parent_index_by_child_index = inverted
22
+ ? generateParentIndexes ( packed_data . inverted_no_imports_nodes )
23
+ : null ;
24
+
25
+ function generateParentIndexes ( nodes ) {
26
+ let ret = new Array ( nodes . children . length ) ;
22
27
console . log ( "finding parent index for each node" ) ;
23
- for ( const [ parentIndex , children ] of packed_data . nodes . children . entries ( ) ) {
28
+ for ( const [ parentIndex , children ] of nodes . children . entries ( ) ) {
24
29
children . forEach ( ( idx ) => ( ret [ idx ] = parentIndex ) ) ;
25
30
}
26
31
console . assert ( ret [ 0 ] === undefined , "root node has a parent" ) ;
27
32
return ret ;
28
- } ) ( ) ;
29
-
30
- function packedDataToTree ( packedData , rangeStart , rangeEnd ) {
31
- const { strings, nodes, unique_threads } = packedData ;
33
+ }
32
34
35
+ function generateNodeObjects ( strings , nodes ) {
33
36
console . log ( "constructing nodes" ) ;
34
37
const node_objects = nodes . name . map ( ( _ , i ) => ( {
35
38
name : strings [ nodes [ "name" ] [ i ] ] ,
@@ -51,6 +54,83 @@ function packedDataToTree(packedData, rangeStart, rangeEnd) {
51
54
node [ "children" ] = node [ "children" ] . map ( ( idx ) => node_objects [ idx ] ) ;
52
55
}
53
56
57
+ return node_objects ;
58
+ }
59
+
60
+ function initTrees ( packedData ) {
61
+ const {
62
+ strings,
63
+ nodes,
64
+ inverted_no_imports_nodes,
65
+ unique_threads,
66
+ intervals,
67
+ no_imports_interval_list,
68
+ } = packedData ;
69
+
70
+ const flamegraphNodeObjects = generateNodeObjects ( strings , nodes ) ;
71
+ const invertedNoImportsNodeObjects = inverted
72
+ ? generateNodeObjects ( strings , inverted_no_imports_nodes )
73
+ : null ;
74
+
75
+ flamegraphIntervals = intervals ;
76
+ invertedNoImportsIntervals = no_imports_interval_list ;
77
+
78
+ return {
79
+ flamegraphNodeObjects : flamegraphNodeObjects ,
80
+ invertedNoImportsNodeObjects : invertedNoImportsNodeObjects ,
81
+ } ;
82
+ }
83
+
84
+ function findHWMAllocations (
85
+ intervals ,
86
+ node_objects ,
87
+ hwmSnapshot ,
88
+ parent_index_by_child_index
89
+ ) {
90
+ intervals . forEach ( ( interval ) => {
91
+ let [ allocBefore , deallocBefore , nodeIndex , count , bytes ] = interval ;
92
+
93
+ if (
94
+ allocBefore <= hwmSnapshot &&
95
+ ( deallocBefore === null || deallocBefore > hwmSnapshot )
96
+ ) {
97
+ while ( nodeIndex !== undefined ) {
98
+ node_objects [ nodeIndex ] . n_allocations += count ;
99
+ node_objects [ nodeIndex ] . value += bytes ;
100
+ nodeIndex = parent_index_by_child_index [ nodeIndex ] ;
101
+ }
102
+ }
103
+ } ) ;
104
+ }
105
+
106
+ function findLeakedAllocations (
107
+ intervals ,
108
+ node_objects ,
109
+ rangeStart ,
110
+ rangeEnd ,
111
+ parent_index_by_child_index
112
+ ) {
113
+ intervals . forEach ( ( interval ) => {
114
+ let [ allocBefore , deallocBefore , nodeIndex , count , bytes ] = interval ;
115
+
116
+ if (
117
+ allocBefore >= rangeStart &&
118
+ allocBefore <= rangeEnd &&
119
+ ( deallocBefore === null || deallocBefore > rangeEnd )
120
+ ) {
121
+ while ( nodeIndex !== undefined ) {
122
+ node_objects [ nodeIndex ] . n_allocations += count ;
123
+ node_objects [ nodeIndex ] . value += bytes ;
124
+ nodeIndex = parent_index_by_child_index [ nodeIndex ] ;
125
+ }
126
+ }
127
+ } ) ;
128
+ }
129
+
130
+ function packedDataToTree ( packedData , rangeStart , rangeEnd ) {
131
+ const { flamegraphNodeObjects, invertedNoImportsNodeObjects } =
132
+ initTrees ( packedData ) ;
133
+
54
134
const hwms = packedData . high_water_mark_by_snapshot ;
55
135
if ( hwms ) {
56
136
console . log ( "finding highest high water mark in range" ) ;
@@ -113,48 +193,53 @@ function packedDataToTree(packedData, rangeStart, rangeEnd) {
113
193
114
194
// We could binary search rather than using a linear scan...
115
195
console . log ( "finding hwm allocations" ) ;
116
- packedData . intervals . forEach ( ( interval ) => {
117
- let [ allocBefore , deallocBefore , nodeIndex , count , bytes ] = interval ;
118
-
119
- if (
120
- allocBefore <= hwmSnapshot &&
121
- ( deallocBefore === null || deallocBefore > hwmSnapshot )
122
- ) {
123
- while ( nodeIndex !== undefined ) {
124
- node_objects [ nodeIndex ] . n_allocations += count ;
125
- node_objects [ nodeIndex ] . value += bytes ;
126
- nodeIndex = parent_index_by_child_index [ nodeIndex ] ;
127
- }
128
- }
129
- } ) ;
196
+ findHWMAllocations (
197
+ flamegraphIntervals ,
198
+ flamegraphNodeObjects ,
199
+ hwmSnapshot ,
200
+ parent_index_by_child_index
201
+ ) ;
202
+ if ( inverted ) {
203
+ findHWMAllocations (
204
+ invertedNoImportsIntervals ,
205
+ invertedNoImportsNodeObjects ,
206
+ hwmSnapshot ,
207
+ inverted_no_imports_parent_index_by_child_index
208
+ ) ;
209
+ }
130
210
} else {
131
211
// We could binary search rather than using a linear scan...
132
212
console . log ( "finding leaked allocations" ) ;
133
- packedData . intervals . forEach ( ( interval ) => {
134
- let [ allocBefore , deallocBefore , nodeIndex , count , bytes ] = interval ;
135
-
136
- if (
137
- allocBefore >= rangeStart &&
138
- allocBefore <= rangeEnd &&
139
- ( deallocBefore === null || deallocBefore > rangeEnd )
140
- ) {
141
- while ( nodeIndex !== undefined ) {
142
- node_objects [ nodeIndex ] . n_allocations += count ;
143
- node_objects [ nodeIndex ] . value += bytes ;
144
- nodeIndex = parent_index_by_child_index [ nodeIndex ] ;
145
- }
146
- }
147
- } ) ;
213
+ findLeakedAllocations (
214
+ flamegraphIntervals ,
215
+ flamegraphNodeObjects ,
216
+ rangeStart ,
217
+ rangeEnd ,
218
+ parent_index_by_child_index
219
+ ) ;
220
+ if ( inverted ) {
221
+ findLeakedAllocations (
222
+ invertedNoImportsIntervals ,
223
+ invertedNoImportsNodeObjects ,
224
+ rangeStart ,
225
+ rangeEnd ,
226
+ inverted_no_imports_parent_index_by_child_index
227
+ ) ;
228
+ }
148
229
}
149
230
150
- console . log ( "total allocations in range: " + node_objects [ 0 ] . n_allocations ) ;
151
- console . log ( "total bytes in range: " + node_objects [ 0 ] . value ) ;
152
-
153
- node_objects . forEach ( ( node ) => {
231
+ flamegraphNodeObjects . forEach ( ( node ) => {
154
232
node . children = node . children . filter ( ( node ) => node . n_allocations > 0 ) ;
155
233
} ) ;
156
234
157
- return node_objects [ 0 ] ;
235
+ if ( inverted ) {
236
+ invertedNoImportsNodeObjects . forEach ( ( node ) => {
237
+ node . children = node . children . filter ( ( node ) => node . n_allocations > 0 ) ;
238
+ } ) ;
239
+ }
240
+
241
+ flamegraphData = flamegraphNodeObjects [ 0 ] ;
242
+ invertedNoImportsData = inverted ? invertedNoImportsNodeObjects [ 0 ] : null ;
158
243
}
159
244
160
245
function initMemoryGraph ( memory_records ) {
@@ -259,7 +344,14 @@ function refreshFlamegraph(event) {
259
344
console . log ( "last possible index is " + memory_records . length ) ;
260
345
261
346
console . log ( "constructing tree" ) ;
262
- data = packedDataToTree ( packed_data , idx0 , idx1 ) ;
347
+ packedDataToTree ( packed_data , idx0 , idx1 ) ;
348
+
349
+ data = inverted && hideImports ? invertedNoImportsData : flamegraphData ;
350
+ intervals =
351
+ inverted && hideImports ? invertedNoImportsIntervals : flamegraphIntervals ;
352
+
353
+ console . log ( "total allocations in range: " + data . n_allocations ) ;
354
+ console . log ( "total bytes in range: " + data . value ) ;
263
355
264
356
console . log ( "drawing chart" ) ;
265
357
getFilteredChart ( ) . drawChart ( data ) ;
0 commit comments