1 | 'use strict'
|
2 |
|
3 | const summary = require('summary')
|
4 |
|
5 | function performanceIssue (issue) {
|
6 | return issue ? 'performance' : 'none'
|
7 | }
|
8 |
|
9 | function analyseMemory (systemInfo, processStatSubset, traceEventSubset) {
|
10 |
|
11 | const blockingEventsNewSpace = new Set(['V8.GCScavenger'])
|
12 | const blockingEventsOldSpace = new Set([
|
13 | 'V8.GCFinalizeMC', 'V8.GCIncrementalMarkingFinalize'
|
14 | ])
|
15 |
|
16 | if (systemInfo.nodeVersion.major < 8) {
|
17 | blockingEventsOldSpace.add('V8.GCIncrementalMarking')
|
18 | }
|
19 |
|
20 |
|
21 |
|
22 |
|
23 |
|
24 |
|
25 | const gcevents = traceEventSubset
|
26 | .filter((d) => blockingEventsNewSpace.has(d.name) || blockingEventsOldSpace.has(d.name))
|
27 | .map((d) => ({
|
28 | name: d.name,
|
29 | timeWindow: Math.round((0.5 / 1000) * (d.args.endTimestamp + d.args.startTimestamp)),
|
30 | duration: d.args.endTimestamp - d.args.startTimestamp
|
31 | }))
|
32 |
|
33 |
|
34 | if (gcevents.length === 0) {
|
35 | return {
|
36 | external: 'none',
|
37 | rss: 'none',
|
38 | heapTotal: 'data',
|
39 | heapUsed: 'data'
|
40 | }
|
41 | }
|
42 |
|
43 |
|
44 | const timeWindows = gcevents.map((d) => d.timeWindow)
|
45 | const timeWindowMax = Math.max(...timeWindows)
|
46 | const timeWindowMin = Math.min(...timeWindows)
|
47 | const timeWindowData = []
|
48 | for (let i = 0; i <= (timeWindowMax - timeWindowMin); i++) {
|
49 | timeWindowData.push([])
|
50 | }
|
51 |
|
52 | for (const gcevent of gcevents) {
|
53 | timeWindowData[gcevent.timeWindow - timeWindowMin].push(gcevent)
|
54 | }
|
55 |
|
56 |
|
57 |
|
58 |
|
59 | const maxBlockedTimeOver1Sec = maxBlockedTime(timeWindowData)
|
60 | const maxBlockedTimeOver1SecNewSpace = maxBlockedTime(
|
61 | timeWindowData.map(
|
62 | (data) => data.filter((d) => blockingEventsNewSpace.has(d.name))
|
63 | )
|
64 | )
|
65 | const maxBlockedTimeOver1SecOldSpace = maxBlockedTime(
|
66 | timeWindowData.map(
|
67 | (data) => data.filter((d) => blockingEventsOldSpace.has(d.name))
|
68 | )
|
69 | )
|
70 |
|
71 | return {
|
72 |
|
73 | external: 'none',
|
74 |
|
75 |
|
76 |
|
77 | rss: 'none',
|
78 |
|
79 |
|
80 |
|
81 |
|
82 |
|
83 |
|
84 | heapTotal: performanceIssue(
|
85 | (maxBlockedTimeOver1Sec >= 100) &&
|
86 | (maxBlockedTimeOver1SecOldSpace >= maxBlockedTimeOver1SecNewSpace)
|
87 | ),
|
88 | heapUsed: performanceIssue(
|
89 | (maxBlockedTimeOver1Sec >= 100) &&
|
90 | (maxBlockedTimeOver1SecOldSpace < maxBlockedTimeOver1SecNewSpace)
|
91 | )
|
92 | }
|
93 | }
|
94 |
|
95 | module.exports = analyseMemory
|
96 |
|
97 | function maxBlockedTime (timeWindowData) {
|
98 | return summary(
|
99 | timeWindowData.map((data) => summary(
|
100 | data.map((d) => d.duration)
|
101 | ).sum())
|
102 | ).max()
|
103 | }
|