dsh-flash-mem-mon 0.1.4 → 0.1.7
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +39 -38
- package/README.zh-CN.md +38 -38
- package/cordis.patch.yml +11 -11
- package/dist/index.js +391 -372
- package/dist/pure.js +66 -0
- package/lib/client.js +2433 -2071
- package/package.json +25 -16
package/dist/pure.js
ADDED
|
@@ -0,0 +1,66 @@
|
|
|
1
|
+
// Pure, dependency-free helpers extracted from index.ts so they can be unit
|
|
2
|
+
// tested without pulling in cordis / node HTTP / GC-entry types. Everything
|
|
3
|
+
// here is a pure function of its inputs.
|
|
4
|
+
export const DEFAULT_ALERT_CONFIG = {
|
|
5
|
+
memThresholdInfo: 256,
|
|
6
|
+
memThresholdWarning: 512,
|
|
7
|
+
memThresholdError: 1024,
|
|
8
|
+
memThresholdCritical: 1536,
|
|
9
|
+
memPollBase: 30000,
|
|
10
|
+
memPollMin: 2000,
|
|
11
|
+
gcThresholdInfo: 2,
|
|
12
|
+
gcThresholdWarning: 5,
|
|
13
|
+
gcThresholdError: 10,
|
|
14
|
+
memGrowthAlertPerMin: 1,
|
|
15
|
+
};
|
|
16
|
+
/**
|
|
17
|
+
* Classify a V8 GC `kind` bitmask as a full (major) cycle.
|
|
18
|
+
*
|
|
19
|
+
* V8 GC entry `kind` is a bitmask:
|
|
20
|
+
* 1 << 0 = Scavenge (minor / young-gen)
|
|
21
|
+
* 1 << 1 = MarkSweepCompact (major / full)
|
|
22
|
+
* 1 << 2 = IncrementalMarking
|
|
23
|
+
* 1 << 3 = ProcessWeakCallbacks
|
|
24
|
+
*
|
|
25
|
+
* In practice modern V8/Node reports a full MarkSweepCompact cycle through the
|
|
26
|
+
* IncrementalMarking (4) and ProcessWeakCallbacks (8) phases — the standalone
|
|
27
|
+
* "major" bit (2) is almost never emitted on its own. Classifying Full GC by
|
|
28
|
+
* `kind === 2` alone therefore misses (nearly) every real full collection.
|
|
29
|
+
* The robust test: a Full GC is any NON-scavenge cycle, i.e. the Scavenge bit
|
|
30
|
+
* (1) is NOT set. This captures 2, 4, 6, 8, 10, 12, 14 while excluding minor
|
|
31
|
+
* (1) scavenges.
|
|
32
|
+
*/
|
|
33
|
+
export function isFullGc(kind) {
|
|
34
|
+
return (kind & 1) === 0 && kind > 0;
|
|
35
|
+
}
|
|
36
|
+
/**
|
|
37
|
+
* Linear-regression slope of `rss` over the last `tailCount` samples, expressed
|
|
38
|
+
* in MB/min. Returns 0 when there are not enough samples (fewer than 3) or the
|
|
39
|
+
* tail time span is not positive.
|
|
40
|
+
*
|
|
41
|
+
* The average sample interval MUST be derived from the tail's OWN first/last
|
|
42
|
+
* timestamps, NOT from the whole buffer span (see index.ts summary()). Using a
|
|
43
|
+
* larger span inflates the interval, deflates samplesPerMin, and under-reports
|
|
44
|
+
* MB/min — a monotonic-leak false negative.
|
|
45
|
+
*/
|
|
46
|
+
export function rssSlopePerMin(samples, tailCount = 20) {
|
|
47
|
+
const tail = samples.slice(-tailCount);
|
|
48
|
+
if (tail.length < 3)
|
|
49
|
+
return 0;
|
|
50
|
+
const n = tail.length;
|
|
51
|
+
let sumX = 0, sumY = 0, sumXY = 0, sumXX = 0;
|
|
52
|
+
for (let i = 0; i < n; i++) {
|
|
53
|
+
sumX += i;
|
|
54
|
+
sumY += tail[i].rss;
|
|
55
|
+
sumXY += i * tail[i].rss;
|
|
56
|
+
sumXX += i * i;
|
|
57
|
+
}
|
|
58
|
+
// slope = bytes per sample-index step.
|
|
59
|
+
const slope = (n * sumXY - sumX * sumY) / (n * sumXX - sumX * sumX);
|
|
60
|
+
const tailSpanMs = Math.max(tail[tail.length - 1].ts - tail[0].ts, 0);
|
|
61
|
+
if (tailSpanMs <= 0)
|
|
62
|
+
return 0;
|
|
63
|
+
const avgIntervalMs = tailSpanMs / (n - 1);
|
|
64
|
+
const samplesPerMinute = 60000 / avgIntervalMs;
|
|
65
|
+
return Math.round((slope * samplesPerMinute / 1048576) * 100) / 100;
|
|
66
|
+
}
|