1 |
|
2 |
|
3 | const summary = require('summary')
|
4 |
|
5 | const MB = 1024 * 1024
|
6 |
|
7 | function analyseMemory (processStatSubset, traceEventSubset) {
|
8 | const heapTotal = processStatSubset.map((d) => d.memory.heapTotal)
|
9 | const heapUsed = processStatSubset.map((d) => d.memory.heapUsed)
|
10 |
|
11 | // Extract delay from blocking Mark & Sweep & Compact events
|
12 | const mscDelay = traceEventSubset
|
13 | .filter((d) => d.name === 'V8.GCMarkSweepCompact')
|
14 | .map((d) => d.args.endTimestamp - d.args.startTimestamp)
|
15 |
|
16 | // The max "old space" size is 1400 MB, if the memory usage is close to
|
17 | // that it can cause an "stop-the-world-gc" issue.
|
18 | const heapTotalStat = summary(heapTotal)
|
19 | const oldSpaceTooLargeIssue = heapTotalStat.max() > 1000 * MB
|
20 |
|
21 | const heapUsedStat = summary(heapUsed)
|
22 |
|
23 | // If MSC caused a big delay
|
24 | const mscDelayStat = summary(mscDelay)
|
25 |
|
26 | // We check if the mean is greater than 100ms.
|
27 | // We use the mean because we want to take into account both
|
28 | // big and small GC events.
|
29 | // mean() could be NaN, and in that case, this check will be false.
|
30 | const mscDelayIssue = mscDelayStat.mean() > 100
|
31 |
|
32 | return {
|
33 | // We are currently not using the external memory processStatSubset
|
34 | 'external': false,
|
35 | // If the user has a lot of code or a huge stack, the RSS could be huge.
|
36 | // This does not necessary indicate an issue, thus RSS is never used
|
37 | // as a measurement feature.
|
38 | 'rss': false,
|
39 | // We should never see huge increases in used heap
|
40 | 'heapTotal': oldSpaceTooLargeIssue,
|
41 | // If Mark & Sweep & Compact caused a delay issue, and we are using
|
42 | // more than 128MB of heap, then we have a problem.
|
43 | 'heapUsed': heapUsedStat.max() > 128 * MB && mscDelayIssue
|
44 | }
|
45 | }
|
46 |
|
47 | module.exports = analyseMemory
|