-
Notifications
You must be signed in to change notification settings - Fork 1
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
feature: add constructor scope to named emitter count measure (#1174)
- Loading branch information
1 parent
f3c24c1
commit a45f060
Showing
8 changed files
with
78 additions
and
129 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
8 changes: 6 additions & 2 deletions
8
packages/heap-snapshot-worker/src/parts/GetConstructorScope/GetConstructorScope.js
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -1,7 +1,11 @@ | ||
export const getConstructorScope = (parsedNodes, constructorScopeMap, node) => { | ||
export const getConstructorScope = (parsedNodes, constructorScopeMap, edgeMap, node) => { | ||
// TODO avoid indexOf | ||
const nodeIndex = parsedNodes.indexOf(node) | ||
const constructorScopeIndex = constructorScopeMap[nodeIndex] | ||
const constructorScope = parsedNodes[constructorScopeIndex] | ||
return constructorScope | ||
const edge = edgeMap[nodeIndex] | ||
return { | ||
scopeNode: constructorScope, | ||
scopeEdge: edge, | ||
} | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
56 changes: 49 additions & 7 deletions
56
...arts/GetNamedConstructorCountFromHeapSnapshot/GetNamedConstructorCountFromHeapSnapshot.js
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -1,18 +1,60 @@ | ||
import * as Assert from '../Assert/Assert.js' | ||
import * as GetConstructorNodes from '../GetConstructorNodes/GetConstructorNodes.js' | ||
import * as GetConstructorScope from '../GetConstructorScope/GetConstructorScope.js' | ||
import * as ParseHeapSnapshot from '../ParseHeapSnapshot/ParseHeapSnapshot.js' | ||
import * as GetConstructorScopeMap from '../GetConstructorScopeMap/GetConstructorScopeMap.js' | ||
import * as GetConstructorNodes from '../GetConstructorNodes/GetConstructorNodes.js' | ||
import * as ParseHeapSnapshot from '../ParseHeapSnapshot/ParseHeapSnapshot.js' | ||
|
||
const createCounts = (constructorNodesWithInfo) => { | ||
const map = Object.create(null) | ||
for (const node of constructorNodesWithInfo) { | ||
map[node.name] ||= 0 | ||
map[node.name]++ | ||
} | ||
const array = Object.entries(map).map(([key, value]) => { | ||
return { | ||
name: key, | ||
count: value, | ||
} | ||
}) | ||
return array | ||
} | ||
|
||
const isImportantScopeName = (name) => { | ||
switch (name) { | ||
case '': | ||
case 'Set': | ||
case 'Array': | ||
case '(object properties)': | ||
case 'system / Context': | ||
return false | ||
default: | ||
return true | ||
} | ||
} | ||
|
||
const getDetailedNodeInfo = (parsedNodes, scopeMap, edgeMap, node) => { | ||
const { scopeNode, scopeEdge } = GetConstructorScope.getConstructorScope(parsedNodes, scopeMap, edgeMap, node) | ||
const parentScope = GetConstructorScope.getConstructorScope(parsedNodes, scopeMap, edgeMap, scopeNode) | ||
if (isImportantScopeName(parentScope.scopeNode.name)) { | ||
const mergedNamed = `${parentScope.scopeNode.name}.${parentScope.scopeEdge} -> ${scopeNode.name}.${scopeEdge}` | ||
return { | ||
name: mergedNamed, | ||
} | ||
} | ||
const mergedNamed = `${scopeNode.name}.${scopeEdge}` | ||
return { | ||
name: mergedNamed, | ||
} | ||
} | ||
|
||
export const getNamedConstructorCountFromHeapSnapshot = async (heapsnapshot, constructorName) => { | ||
Assert.object(heapsnapshot) | ||
const { parsedNodes, graph } = ParseHeapSnapshot.parseHeapSnapshot(heapsnapshot) | ||
const constructorNodes = GetConstructorNodes.getConstructorNodes(parsedNodes, constructorName) | ||
const constructorScopeMap = GetConstructorScopeMap.getConstructorScopeMap(parsedNodes, graph) | ||
const { scopeMap, edgeMap } = GetConstructorScopeMap.getConstructorScopeMap(parsedNodes, graph) | ||
const constructorNodesWithInfo = constructorNodes.map((node) => { | ||
const constructorScope = GetConstructorScope.getConstructorScope(parsedNodes, constructorScopeMap, node) | ||
const mergedNamed = `${constructorScope.name}:${node.name}` | ||
return mergedNamed | ||
return getDetailedNodeInfo(parsedNodes, scopeMap, edgeMap, node) | ||
}) | ||
return constructorNodesWithInfo | ||
const counts = createCounts(constructorNodesWithInfo) | ||
return counts | ||
} |
115 changes: 4 additions & 111 deletions
115
...er/src/parts/GetNamedEmitterCountFromHeapSnapshot/GetNamedEmitterCountFromHeapSnapshot.js
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -1,116 +1,9 @@ | ||
import * as Assert from '../Assert/Assert.js' | ||
import * as CreateNameMap from '../CreateNameMap/CreateNameMap.js' | ||
import * as ParseHeapSnapshot from '../ParseHeapSnapshot/ParseHeapSnapshot.js' | ||
import * as SortCountMap from '../SortCountMap/SortCountMap.js' | ||
|
||
const createCountMap = (names) => { | ||
const map = Object.create(null) | ||
for (const name of names) { | ||
map[name] ||= 0 | ||
map[name]++ | ||
} | ||
return map | ||
} | ||
|
||
const filterByArray = (value) => { | ||
return value.nodeName === 'Array' | ||
} | ||
|
||
const getValueName = (value) => { | ||
return value.edgeName || value.nodeName | ||
} | ||
|
||
const getArrayNames = (nameMap) => { | ||
const values = Object.values(nameMap) | ||
const filtered = values.filter(filterByArray) | ||
const mapped = filtered.map(getValueName) | ||
return mapped | ||
} | ||
|
||
const getArrayNamesWithCount = (countMap) => { | ||
const arrayNamesWithCount = Object.entries(countMap).map(([key, value]) => { | ||
return { | ||
name: key, | ||
count: value, | ||
} | ||
}) | ||
return arrayNamesWithCount | ||
} | ||
|
||
const isEventEmitterConstructorCandidate = (node) => { | ||
return node.type === 'object' && node.name === 'Emitter' | ||
} | ||
|
||
const getEventEmitterNode = (nodes, graph) => { | ||
const candidates = nodes.filter(isEventEmitterConstructorCandidate) | ||
const allEdges = Object.values(graph).flat(1) | ||
const explorerRootEdge = allEdges.find((edge) => edge.name === 'explorerRootErrorEmitter') | ||
for (const candidate of candidates) { | ||
const index = nodes.indexOf(candidate) | ||
if (explorerRootEdge.index === index) { | ||
return candidate | ||
} | ||
} | ||
return undefined | ||
} | ||
|
||
const RE_NUMERIC = /^\d+$/ | ||
|
||
const isRelevantEdge = (edge) => { | ||
const { name } = edge | ||
if (name === 'this') { | ||
return false | ||
} | ||
if (RE_NUMERIC.test(name)) { | ||
return false | ||
} | ||
return true | ||
} | ||
|
||
const createCountedValues = (names) => { | ||
const countMap = Object.create(null) | ||
for (const name of names) { | ||
countMap[name] ||= 0 | ||
countMap[name]++ | ||
} | ||
const entries = Object.entries(countMap) | ||
const result = entries.map(([key, value]) => { | ||
return { | ||
name: key, | ||
count: value, | ||
} | ||
}) | ||
return result | ||
} | ||
|
||
const anonymousEdge = { | ||
index: -1, | ||
name: '<anonymous>', | ||
} | ||
import * as GetNamedConstructorCountFromHeapSnapshot from '../GetNamedConstructorCountFromHeapSnapshot/GetNamedConstructorCountFromHeapSnapshot.js' | ||
|
||
export const getNamedEmitterCountFromHeapSnapshot = async (heapsnapshot) => { | ||
Assert.object(heapsnapshot) | ||
const { parsedNodes, graph } = ParseHeapSnapshot.parseHeapSnapshot(heapsnapshot) | ||
const emitters = parsedNodes.filter(isEventEmitterConstructorCandidate) | ||
const allEdges = Object.values(graph).flat(1) | ||
const allValues = [] | ||
const indices = emitters.map((emitter) => { | ||
return parsedNodes.indexOf(emitter) | ||
}) | ||
const indicesSet = new Set(indices) | ||
const reverseMap = Object.create(null) | ||
for (const edge of allEdges) { | ||
if (indicesSet.has(edge.index)) { | ||
reverseMap[edge.index] ||= [] | ||
reverseMap[edge.index].push(edge) | ||
} | ||
} | ||
for (const item of emitters) { | ||
const index = parsedNodes.indexOf(item) | ||
const matchingEdges = reverseMap[index] || [] | ||
const relevantEdge = matchingEdges.find(isRelevantEdge) || anonymousEdge | ||
allValues.push(relevantEdge.name) | ||
} | ||
const countedValues = createCountedValues(allValues) | ||
return countedValues | ||
const constructorName = 'Emitter' | ||
const info = GetNamedConstructorCountFromHeapSnapshot.getNamedConstructorCountFromHeapSnapshot(heapsnapshot, constructorName) | ||
return info | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters