@trillboards/edge-core 0.2.2 → 0.3.0
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/dist/MemoryAttenuationManager.d.ts +164 -0
- package/dist/MemoryAttenuationManager.d.ts.map +1 -0
- package/dist/MemoryAttenuationManager.js +400 -0
- package/dist/MemoryAttenuationManager.js.map +1 -0
- package/dist/ModelManager.d.ts +166 -0
- package/dist/ModelManager.d.ts.map +1 -0
- package/dist/ModelManager.js +580 -0
- package/dist/ModelManager.js.map +1 -0
- package/dist/StatusServer.d.ts +99 -0
- package/dist/StatusServer.d.ts.map +1 -0
- package/dist/StatusServer.js +262 -0
- package/dist/StatusServer.js.map +1 -0
- package/dist/ZKAudienceProver.d.ts +137 -0
- package/dist/ZKAudienceProver.d.ts.map +1 -0
- package/dist/ZKAudienceProver.js +321 -0
- package/dist/ZKAudienceProver.js.map +1 -0
- package/dist/index.d.ts +9 -0
- package/dist/index.d.ts.map +1 -1
- package/dist/index.js +11 -1
- package/dist/index.js.map +1 -1
- package/dist/types.d.ts +51 -0
- package/dist/types.d.ts.map +1 -1
- package/dist/types.js.map +1 -1
- package/package.json +2 -1
|
@@ -0,0 +1,164 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* MemoryAttenuationManager — Monitors V8 heap and OS memory, applies tiered
|
|
3
|
+
* shedding to keep edge devices stable under pressure.
|
|
4
|
+
*
|
|
5
|
+
* Port of CTV agent's MemoryAttenuationManager.kt, adapted for the V8 heap
|
|
6
|
+
* model. Uses `process.memoryUsage()` for heap metrics and `os.freemem()` /
|
|
7
|
+
* `os.totalmem()` for system-level awareness.
|
|
8
|
+
*
|
|
9
|
+
* Tiers (based on heap usage percentage = heapUsed / heapTotal):
|
|
10
|
+
* GREEN — Normal operation, all systems active
|
|
11
|
+
* YELLOW — >70% heap — disable cloud inference
|
|
12
|
+
* ORANGE — >80% heap — disable federated learning, reduce FPS
|
|
13
|
+
* RED — >90% heap — shed lowest-priority models (one per cycle)
|
|
14
|
+
* CRITICAL — >95% heap — camera-only emergency mode, force GC
|
|
15
|
+
*
|
|
16
|
+
* Hysteresis prevents oscillation: a tier is only restored when usage drops
|
|
17
|
+
* a configurable percentage (default 15%) below the threshold that triggered
|
|
18
|
+
* escalation. For example, YELLOW triggers at 70% but only restores to GREEN
|
|
19
|
+
* when usage falls below 55%.
|
|
20
|
+
*/
|
|
21
|
+
/// <reference types="node" />
|
|
22
|
+
import { EventEmitter } from 'events';
|
|
23
|
+
export declare enum MemoryTier {
|
|
24
|
+
GREEN = "GREEN",
|
|
25
|
+
YELLOW = "YELLOW",
|
|
26
|
+
ORANGE = "ORANGE",
|
|
27
|
+
RED = "RED",
|
|
28
|
+
CRITICAL = "CRITICAL"
|
|
29
|
+
}
|
|
30
|
+
export interface MemorySnapshot {
|
|
31
|
+
heapUsedMb: number;
|
|
32
|
+
heapTotalMb: number;
|
|
33
|
+
heapUsedPercent: number;
|
|
34
|
+
rssUsedMb: number;
|
|
35
|
+
osFreeMemMb: number;
|
|
36
|
+
osTotalMemMb: number;
|
|
37
|
+
osUsedPercent: number;
|
|
38
|
+
tier: MemoryTier;
|
|
39
|
+
timestamp: number;
|
|
40
|
+
}
|
|
41
|
+
export interface AttenuationAction {
|
|
42
|
+
tier: MemoryTier;
|
|
43
|
+
action: string;
|
|
44
|
+
timestamp: number;
|
|
45
|
+
}
|
|
46
|
+
export interface AttenuationCallbacks {
|
|
47
|
+
onDisableCloudInference: () => void;
|
|
48
|
+
onEnableCloudInference: () => void;
|
|
49
|
+
onDisableFederatedLearning: () => void;
|
|
50
|
+
onEnableFederatedLearning: () => void;
|
|
51
|
+
onReduceSensingFps: (targetFps: number) => void;
|
|
52
|
+
onRestoreSensingFps: (targetFps: number) => void;
|
|
53
|
+
onShedModel: (modelName: string) => void;
|
|
54
|
+
onRestoreModel: (modelName: string) => void;
|
|
55
|
+
onForceGC: () => void;
|
|
56
|
+
onEmergencyMode: () => void;
|
|
57
|
+
onRestoreNormal: () => void;
|
|
58
|
+
}
|
|
59
|
+
export interface MemoryAttenuationManagerOptions {
|
|
60
|
+
callbacks: AttenuationCallbacks;
|
|
61
|
+
/** Polling interval in milliseconds. Default: 10000 (10s). */
|
|
62
|
+
checkIntervalMs?: number;
|
|
63
|
+
/** Heap usage fraction to enter YELLOW. Default: 0.70. */
|
|
64
|
+
yellowThreshold?: number;
|
|
65
|
+
/** Heap usage fraction to enter ORANGE. Default: 0.80. */
|
|
66
|
+
orangeThreshold?: number;
|
|
67
|
+
/** Heap usage fraction to enter RED. Default: 0.90. */
|
|
68
|
+
redThreshold?: number;
|
|
69
|
+
/** Heap usage fraction to enter CRITICAL. Default: 0.95. */
|
|
70
|
+
criticalThreshold?: number;
|
|
71
|
+
/** Fraction below threshold before restoring to a lower tier. Default: 0.15. */
|
|
72
|
+
hysteresisPercent?: number;
|
|
73
|
+
/** Normal sensing FPS, restored when dropping below ORANGE. Default: 8. */
|
|
74
|
+
normalFps?: number;
|
|
75
|
+
/** Reduced sensing FPS used at ORANGE and above. Default: 2. */
|
|
76
|
+
reducedFps?: number;
|
|
77
|
+
/**
|
|
78
|
+
* Model shed order from *least important* (index 0, shed first) to
|
|
79
|
+
* *most important* (last index, shed last). During RED, one model is shed
|
|
80
|
+
* per check cycle starting from the end of this array.
|
|
81
|
+
*
|
|
82
|
+
* Default: ['yamnet', 'whisperAsr', 'ferEmotion', 'poseEngagement', 'ageGender', 'gazeTracking']
|
|
83
|
+
*/
|
|
84
|
+
shedOrder?: string[];
|
|
85
|
+
}
|
|
86
|
+
export declare class MemoryAttenuationManager extends EventEmitter {
|
|
87
|
+
private readonly callbacks;
|
|
88
|
+
private readonly checkIntervalMs;
|
|
89
|
+
private readonly yellowThreshold;
|
|
90
|
+
private readonly orangeThreshold;
|
|
91
|
+
private readonly redThreshold;
|
|
92
|
+
private readonly criticalThreshold;
|
|
93
|
+
private readonly hysteresisPercent;
|
|
94
|
+
private readonly normalFps;
|
|
95
|
+
private readonly reducedFps;
|
|
96
|
+
private readonly shedOrder;
|
|
97
|
+
private currentTier;
|
|
98
|
+
private intervalHandle;
|
|
99
|
+
private history;
|
|
100
|
+
private actions;
|
|
101
|
+
private cloudInferenceDisabled;
|
|
102
|
+
private federatedLearningDisabled;
|
|
103
|
+
private fpsReduced;
|
|
104
|
+
private shedModels;
|
|
105
|
+
private emergencyModeActive;
|
|
106
|
+
constructor(options: MemoryAttenuationManagerOptions);
|
|
107
|
+
/**
|
|
108
|
+
* Start the periodic memory monitoring interval. The timer is `unref()`'d
|
|
109
|
+
* so it will not keep the Node.js event loop alive on its own.
|
|
110
|
+
*/
|
|
111
|
+
start(): void;
|
|
112
|
+
/** Stop the periodic monitoring interval. */
|
|
113
|
+
stop(): void;
|
|
114
|
+
/** Return the current memory tier. */
|
|
115
|
+
getCurrentTier(): MemoryTier;
|
|
116
|
+
/** Take a point-in-time memory snapshot (does NOT trigger actions). */
|
|
117
|
+
getSnapshot(): MemorySnapshot;
|
|
118
|
+
/** Return the last N snapshots (up to 100). */
|
|
119
|
+
getHistory(): MemorySnapshot[];
|
|
120
|
+
/** Return the list of model names currently shed. */
|
|
121
|
+
getShedModels(): string[];
|
|
122
|
+
/** Return the full log of attenuation actions taken. */
|
|
123
|
+
getActions(): AttenuationAction[];
|
|
124
|
+
/**
|
|
125
|
+
* Single check cycle. Exposed as package-internal so tests can drive it
|
|
126
|
+
* deterministically without timers.
|
|
127
|
+
*/
|
|
128
|
+
check(): void;
|
|
129
|
+
/**
|
|
130
|
+
* Classify a heap usage percentage into a MemoryTier, applying hysteresis
|
|
131
|
+
* to prevent oscillation at tier boundaries.
|
|
132
|
+
*
|
|
133
|
+
* Escalation uses the raw threshold (jumps to the highest applicable tier).
|
|
134
|
+
* Restoration requires the usage to drop below `threshold - hysteresisPercent`
|
|
135
|
+
* at each boundary, and walks down through all qualifying tiers in a single
|
|
136
|
+
* check. For example with default settings:
|
|
137
|
+
* - Escalate to YELLOW at 70%, restore to GREEN below 55% (70 - 15)
|
|
138
|
+
* - Escalate to ORANGE at 80%, restore to YELLOW below 65% (80 - 15)
|
|
139
|
+
* - Escalate to RED at 90%, restore to ORANGE below 75% (90 - 15)
|
|
140
|
+
* - Escalate to CRITICAL at 95%, restore to RED below 80% (95 - 15)
|
|
141
|
+
*/
|
|
142
|
+
private classifyTier;
|
|
143
|
+
/** Apply the actions for entering a given tier (escalating). */
|
|
144
|
+
private applyEscalation;
|
|
145
|
+
/**
|
|
146
|
+
* Apply the restoration actions for entering a given tier (de-escalating).
|
|
147
|
+
* `tier` is the tier we are *entering* on the way down.
|
|
148
|
+
*/
|
|
149
|
+
private applyRestoration;
|
|
150
|
+
/**
|
|
151
|
+
* Shed the next model in the shed order. Models are shed from the *end*
|
|
152
|
+
* of `shedOrder` (lowest priority) toward the beginning (highest priority).
|
|
153
|
+
* One model per call.
|
|
154
|
+
*/
|
|
155
|
+
private shedNextModel;
|
|
156
|
+
/**
|
|
157
|
+
* Restore all shed models in reverse order (highest priority first,
|
|
158
|
+
* i.e., from the beginning of `shedOrder`).
|
|
159
|
+
*/
|
|
160
|
+
private restoreAllShedModels;
|
|
161
|
+
private takeSnapshot;
|
|
162
|
+
private recordAction;
|
|
163
|
+
}
|
|
164
|
+
//# sourceMappingURL=MemoryAttenuationManager.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"MemoryAttenuationManager.d.ts","sourceRoot":"","sources":["../src/MemoryAttenuationManager.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,400 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
/**
|
|
3
|
+
* MemoryAttenuationManager — Monitors V8 heap and OS memory, applies tiered
|
|
4
|
+
* shedding to keep edge devices stable under pressure.
|
|
5
|
+
*
|
|
6
|
+
* Port of CTV agent's MemoryAttenuationManager.kt, adapted for the V8 heap
|
|
7
|
+
* model. Uses `process.memoryUsage()` for heap metrics and `os.freemem()` /
|
|
8
|
+
* `os.totalmem()` for system-level awareness.
|
|
9
|
+
*
|
|
10
|
+
* Tiers (based on heap usage percentage = heapUsed / heapTotal):
|
|
11
|
+
* GREEN — Normal operation, all systems active
|
|
12
|
+
* YELLOW — >70% heap — disable cloud inference
|
|
13
|
+
* ORANGE — >80% heap — disable federated learning, reduce FPS
|
|
14
|
+
* RED — >90% heap — shed lowest-priority models (one per cycle)
|
|
15
|
+
* CRITICAL — >95% heap — camera-only emergency mode, force GC
|
|
16
|
+
*
|
|
17
|
+
* Hysteresis prevents oscillation: a tier is only restored when usage drops
|
|
18
|
+
* a configurable percentage (default 15%) below the threshold that triggered
|
|
19
|
+
* escalation. For example, YELLOW triggers at 70% but only restores to GREEN
|
|
20
|
+
* when usage falls below 55%.
|
|
21
|
+
*/
|
|
22
|
+
var __createBinding = (this && this.__createBinding) || (Object.create ? (function(o, m, k, k2) {
|
|
23
|
+
if (k2 === undefined) k2 = k;
|
|
24
|
+
var desc = Object.getOwnPropertyDescriptor(m, k);
|
|
25
|
+
if (!desc || ("get" in desc ? !m.__esModule : desc.writable || desc.configurable)) {
|
|
26
|
+
desc = { enumerable: true, get: function() { return m[k]; } };
|
|
27
|
+
}
|
|
28
|
+
Object.defineProperty(o, k2, desc);
|
|
29
|
+
}) : (function(o, m, k, k2) {
|
|
30
|
+
if (k2 === undefined) k2 = k;
|
|
31
|
+
o[k2] = m[k];
|
|
32
|
+
}));
|
|
33
|
+
var __setModuleDefault = (this && this.__setModuleDefault) || (Object.create ? (function(o, v) {
|
|
34
|
+
Object.defineProperty(o, "default", { enumerable: true, value: v });
|
|
35
|
+
}) : function(o, v) {
|
|
36
|
+
o["default"] = v;
|
|
37
|
+
});
|
|
38
|
+
var __importStar = (this && this.__importStar) || function (mod) {
|
|
39
|
+
if (mod && mod.__esModule) return mod;
|
|
40
|
+
var result = {};
|
|
41
|
+
if (mod != null) for (var k in mod) if (k !== "default" && Object.prototype.hasOwnProperty.call(mod, k)) __createBinding(result, mod, k);
|
|
42
|
+
__setModuleDefault(result, mod);
|
|
43
|
+
return result;
|
|
44
|
+
};
|
|
45
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
46
|
+
exports.MemoryAttenuationManager = exports.MemoryTier = void 0;
|
|
47
|
+
const events_1 = require("events");
|
|
48
|
+
const os = __importStar(require("os"));
|
|
49
|
+
// ─── Public Types ───────────────────────────────────────────────────────────
|
|
50
|
+
var MemoryTier;
|
|
51
|
+
(function (MemoryTier) {
|
|
52
|
+
MemoryTier["GREEN"] = "GREEN";
|
|
53
|
+
MemoryTier["YELLOW"] = "YELLOW";
|
|
54
|
+
MemoryTier["ORANGE"] = "ORANGE";
|
|
55
|
+
MemoryTier["RED"] = "RED";
|
|
56
|
+
MemoryTier["CRITICAL"] = "CRITICAL";
|
|
57
|
+
})(MemoryTier || (exports.MemoryTier = MemoryTier = {}));
|
|
58
|
+
// ─── Internal Constants ─────────────────────────────────────────────────────
|
|
59
|
+
const MB = 1024 * 1024;
|
|
60
|
+
const MAX_HISTORY = 100;
|
|
61
|
+
const MAX_ACTIONS = 200;
|
|
62
|
+
const DEFAULT_CHECK_INTERVAL_MS = 10000;
|
|
63
|
+
const DEFAULT_YELLOW_THRESHOLD = 0.70;
|
|
64
|
+
const DEFAULT_ORANGE_THRESHOLD = 0.80;
|
|
65
|
+
const DEFAULT_RED_THRESHOLD = 0.90;
|
|
66
|
+
const DEFAULT_CRITICAL_THRESHOLD = 0.95;
|
|
67
|
+
const DEFAULT_HYSTERESIS_PERCENT = 0.15;
|
|
68
|
+
const DEFAULT_NORMAL_FPS = 8;
|
|
69
|
+
const DEFAULT_REDUCED_FPS = 2;
|
|
70
|
+
const DEFAULT_SHED_ORDER = [
|
|
71
|
+
'yamnet',
|
|
72
|
+
'whisperAsr',
|
|
73
|
+
'ferEmotion',
|
|
74
|
+
'poseEngagement',
|
|
75
|
+
'ageGender',
|
|
76
|
+
'gazeTracking',
|
|
77
|
+
];
|
|
78
|
+
/**
|
|
79
|
+
* Ordered tier list from lowest severity to highest. Used for comparison
|
|
80
|
+
* and iteration when escalating or restoring.
|
|
81
|
+
*/
|
|
82
|
+
const TIER_SEVERITY = [
|
|
83
|
+
MemoryTier.GREEN,
|
|
84
|
+
MemoryTier.YELLOW,
|
|
85
|
+
MemoryTier.ORANGE,
|
|
86
|
+
MemoryTier.RED,
|
|
87
|
+
MemoryTier.CRITICAL,
|
|
88
|
+
];
|
|
89
|
+
function tierIndex(tier) {
|
|
90
|
+
return TIER_SEVERITY.indexOf(tier);
|
|
91
|
+
}
|
|
92
|
+
// ─── Implementation ─────────────────────────────────────────────────────────
|
|
93
|
+
class MemoryAttenuationManager extends events_1.EventEmitter {
|
|
94
|
+
constructor(options) {
|
|
95
|
+
super();
|
|
96
|
+
// Runtime state
|
|
97
|
+
this.currentTier = MemoryTier.GREEN;
|
|
98
|
+
this.intervalHandle = null;
|
|
99
|
+
this.history = [];
|
|
100
|
+
this.actions = [];
|
|
101
|
+
// Tracked attenuation state — what we have already told callers to do
|
|
102
|
+
this.cloudInferenceDisabled = false;
|
|
103
|
+
this.federatedLearningDisabled = false;
|
|
104
|
+
this.fpsReduced = false;
|
|
105
|
+
this.shedModels = new Set();
|
|
106
|
+
this.emergencyModeActive = false;
|
|
107
|
+
this.callbacks = options.callbacks;
|
|
108
|
+
this.checkIntervalMs = options.checkIntervalMs ?? DEFAULT_CHECK_INTERVAL_MS;
|
|
109
|
+
this.yellowThreshold = options.yellowThreshold ?? DEFAULT_YELLOW_THRESHOLD;
|
|
110
|
+
this.orangeThreshold = options.orangeThreshold ?? DEFAULT_ORANGE_THRESHOLD;
|
|
111
|
+
this.redThreshold = options.redThreshold ?? DEFAULT_RED_THRESHOLD;
|
|
112
|
+
this.criticalThreshold = options.criticalThreshold ?? DEFAULT_CRITICAL_THRESHOLD;
|
|
113
|
+
this.hysteresisPercent = options.hysteresisPercent ?? DEFAULT_HYSTERESIS_PERCENT;
|
|
114
|
+
this.normalFps = options.normalFps ?? DEFAULT_NORMAL_FPS;
|
|
115
|
+
this.reducedFps = options.reducedFps ?? DEFAULT_REDUCED_FPS;
|
|
116
|
+
this.shedOrder = options.shedOrder ? [...options.shedOrder] : [...DEFAULT_SHED_ORDER];
|
|
117
|
+
}
|
|
118
|
+
// ─── Public API ─────────────────────────────────────────────────────────
|
|
119
|
+
/**
|
|
120
|
+
* Start the periodic memory monitoring interval. The timer is `unref()`'d
|
|
121
|
+
* so it will not keep the Node.js event loop alive on its own.
|
|
122
|
+
*/
|
|
123
|
+
start() {
|
|
124
|
+
if (this.intervalHandle !== null)
|
|
125
|
+
return;
|
|
126
|
+
this.intervalHandle = setInterval(() => this.check(), this.checkIntervalMs);
|
|
127
|
+
this.intervalHandle.unref();
|
|
128
|
+
}
|
|
129
|
+
/** Stop the periodic monitoring interval. */
|
|
130
|
+
stop() {
|
|
131
|
+
if (this.intervalHandle !== null) {
|
|
132
|
+
clearInterval(this.intervalHandle);
|
|
133
|
+
this.intervalHandle = null;
|
|
134
|
+
}
|
|
135
|
+
}
|
|
136
|
+
/** Return the current memory tier. */
|
|
137
|
+
getCurrentTier() {
|
|
138
|
+
return this.currentTier;
|
|
139
|
+
}
|
|
140
|
+
/** Take a point-in-time memory snapshot (does NOT trigger actions). */
|
|
141
|
+
getSnapshot() {
|
|
142
|
+
return this.takeSnapshot();
|
|
143
|
+
}
|
|
144
|
+
/** Return the last N snapshots (up to 100). */
|
|
145
|
+
getHistory() {
|
|
146
|
+
return [...this.history];
|
|
147
|
+
}
|
|
148
|
+
/** Return the list of model names currently shed. */
|
|
149
|
+
getShedModels() {
|
|
150
|
+
return [...this.shedModels];
|
|
151
|
+
}
|
|
152
|
+
/** Return the full log of attenuation actions taken. */
|
|
153
|
+
getActions() {
|
|
154
|
+
return [...this.actions];
|
|
155
|
+
}
|
|
156
|
+
// ─── Core Check Loop ───────────────────────────────────────────────────
|
|
157
|
+
/**
|
|
158
|
+
* Single check cycle. Exposed as package-internal so tests can drive it
|
|
159
|
+
* deterministically without timers.
|
|
160
|
+
*/
|
|
161
|
+
check() {
|
|
162
|
+
const snapshot = this.takeSnapshot();
|
|
163
|
+
// Record history (ring buffer, capped at MAX_HISTORY)
|
|
164
|
+
this.history.push(snapshot);
|
|
165
|
+
if (this.history.length > MAX_HISTORY) {
|
|
166
|
+
this.history.shift();
|
|
167
|
+
}
|
|
168
|
+
const newTier = this.classifyTier(snapshot.heapUsedPercent);
|
|
169
|
+
if (newTier !== this.currentTier) {
|
|
170
|
+
const previousTier = this.currentTier;
|
|
171
|
+
this.currentTier = newTier;
|
|
172
|
+
snapshot.tier = newTier;
|
|
173
|
+
// Apply actions for every step between old and new tier
|
|
174
|
+
const oldIdx = tierIndex(previousTier);
|
|
175
|
+
const newIdx = tierIndex(newTier);
|
|
176
|
+
if (newIdx > oldIdx) {
|
|
177
|
+
// Escalating — apply each step from old+1 up to new
|
|
178
|
+
for (let i = oldIdx + 1; i <= newIdx; i++) {
|
|
179
|
+
this.applyEscalation(TIER_SEVERITY[i]);
|
|
180
|
+
}
|
|
181
|
+
}
|
|
182
|
+
else {
|
|
183
|
+
// Restoring — apply each step from old-1 down to new
|
|
184
|
+
for (let i = oldIdx - 1; i >= newIdx; i--) {
|
|
185
|
+
this.applyRestoration(TIER_SEVERITY[i]);
|
|
186
|
+
}
|
|
187
|
+
}
|
|
188
|
+
this.emit('tierChanged', {
|
|
189
|
+
from: previousTier,
|
|
190
|
+
to: newTier,
|
|
191
|
+
snapshot,
|
|
192
|
+
});
|
|
193
|
+
}
|
|
194
|
+
else if (newTier === MemoryTier.RED) {
|
|
195
|
+
// While staying in RED, shed one more model per cycle if available
|
|
196
|
+
this.shedNextModel();
|
|
197
|
+
}
|
|
198
|
+
}
|
|
199
|
+
// ─── Tier Classification (with hysteresis) ─────────────────────────────
|
|
200
|
+
/**
|
|
201
|
+
* Classify a heap usage percentage into a MemoryTier, applying hysteresis
|
|
202
|
+
* to prevent oscillation at tier boundaries.
|
|
203
|
+
*
|
|
204
|
+
* Escalation uses the raw threshold (jumps to the highest applicable tier).
|
|
205
|
+
* Restoration requires the usage to drop below `threshold - hysteresisPercent`
|
|
206
|
+
* at each boundary, and walks down through all qualifying tiers in a single
|
|
207
|
+
* check. For example with default settings:
|
|
208
|
+
* - Escalate to YELLOW at 70%, restore to GREEN below 55% (70 - 15)
|
|
209
|
+
* - Escalate to ORANGE at 80%, restore to YELLOW below 65% (80 - 15)
|
|
210
|
+
* - Escalate to RED at 90%, restore to ORANGE below 75% (90 - 15)
|
|
211
|
+
* - Escalate to CRITICAL at 95%, restore to RED below 80% (95 - 15)
|
|
212
|
+
*/
|
|
213
|
+
classifyTier(heapUsedPercent) {
|
|
214
|
+
const currentIdx = tierIndex(this.currentTier);
|
|
215
|
+
// Check for escalation (use raw thresholds, jump to highest applicable)
|
|
216
|
+
if (heapUsedPercent >= this.criticalThreshold * 100 && currentIdx < tierIndex(MemoryTier.CRITICAL)) {
|
|
217
|
+
return MemoryTier.CRITICAL;
|
|
218
|
+
}
|
|
219
|
+
if (heapUsedPercent >= this.redThreshold * 100 && currentIdx < tierIndex(MemoryTier.RED)) {
|
|
220
|
+
return MemoryTier.RED;
|
|
221
|
+
}
|
|
222
|
+
if (heapUsedPercent >= this.orangeThreshold * 100 && currentIdx < tierIndex(MemoryTier.ORANGE)) {
|
|
223
|
+
return MemoryTier.ORANGE;
|
|
224
|
+
}
|
|
225
|
+
if (heapUsedPercent >= this.yellowThreshold * 100 && currentIdx < tierIndex(MemoryTier.YELLOW)) {
|
|
226
|
+
return MemoryTier.YELLOW;
|
|
227
|
+
}
|
|
228
|
+
// Check for restoration — walk downward through each tier boundary,
|
|
229
|
+
// applying hysteresis at each step. This allows multi-step drops in a
|
|
230
|
+
// single check when memory falls far enough.
|
|
231
|
+
const hysteresisThresholds = [
|
|
232
|
+
{ tier: MemoryTier.CRITICAL, restoreBelow: (this.criticalThreshold - this.hysteresisPercent) * 100 },
|
|
233
|
+
{ tier: MemoryTier.RED, restoreBelow: (this.redThreshold - this.hysteresisPercent) * 100 },
|
|
234
|
+
{ tier: MemoryTier.ORANGE, restoreBelow: (this.orangeThreshold - this.hysteresisPercent) * 100 },
|
|
235
|
+
{ tier: MemoryTier.YELLOW, restoreBelow: (this.yellowThreshold - this.hysteresisPercent) * 100 },
|
|
236
|
+
];
|
|
237
|
+
let resolvedTier = this.currentTier;
|
|
238
|
+
for (const { tier, restoreBelow } of hysteresisThresholds) {
|
|
239
|
+
if (resolvedTier === tier && heapUsedPercent < restoreBelow) {
|
|
240
|
+
// Drop one level
|
|
241
|
+
const idx = tierIndex(tier);
|
|
242
|
+
resolvedTier = TIER_SEVERITY[idx - 1];
|
|
243
|
+
}
|
|
244
|
+
}
|
|
245
|
+
return resolvedTier;
|
|
246
|
+
}
|
|
247
|
+
// ─── Escalation Actions ────────────────────────────────────────────────
|
|
248
|
+
/** Apply the actions for entering a given tier (escalating). */
|
|
249
|
+
applyEscalation(tier) {
|
|
250
|
+
switch (tier) {
|
|
251
|
+
case MemoryTier.YELLOW:
|
|
252
|
+
if (!this.cloudInferenceDisabled) {
|
|
253
|
+
this.cloudInferenceDisabled = true;
|
|
254
|
+
this.callbacks.onDisableCloudInference();
|
|
255
|
+
this.recordAction(tier, 'disable_cloud_inference');
|
|
256
|
+
}
|
|
257
|
+
break;
|
|
258
|
+
case MemoryTier.ORANGE:
|
|
259
|
+
if (!this.federatedLearningDisabled) {
|
|
260
|
+
this.federatedLearningDisabled = true;
|
|
261
|
+
this.callbacks.onDisableFederatedLearning();
|
|
262
|
+
this.recordAction(tier, 'disable_federated_learning');
|
|
263
|
+
}
|
|
264
|
+
if (!this.fpsReduced) {
|
|
265
|
+
this.fpsReduced = true;
|
|
266
|
+
this.callbacks.onReduceSensingFps(this.reducedFps);
|
|
267
|
+
this.recordAction(tier, `reduce_fps_to_${this.reducedFps}`);
|
|
268
|
+
}
|
|
269
|
+
break;
|
|
270
|
+
case MemoryTier.RED:
|
|
271
|
+
this.shedNextModel();
|
|
272
|
+
break;
|
|
273
|
+
case MemoryTier.CRITICAL:
|
|
274
|
+
if (!this.emergencyModeActive) {
|
|
275
|
+
this.emergencyModeActive = true;
|
|
276
|
+
this.callbacks.onEmergencyMode();
|
|
277
|
+
this.recordAction(tier, 'emergency_mode');
|
|
278
|
+
}
|
|
279
|
+
// Attempt GC if exposed via --expose-gc
|
|
280
|
+
if (typeof global.gc === 'function') {
|
|
281
|
+
global.gc();
|
|
282
|
+
}
|
|
283
|
+
this.callbacks.onForceGC();
|
|
284
|
+
this.recordAction(tier, 'force_gc');
|
|
285
|
+
break;
|
|
286
|
+
case MemoryTier.GREEN:
|
|
287
|
+
// No escalation action for GREEN
|
|
288
|
+
break;
|
|
289
|
+
}
|
|
290
|
+
}
|
|
291
|
+
// ─── Restoration Actions ───────────────────────────────────────────────
|
|
292
|
+
/**
|
|
293
|
+
* Apply the restoration actions for entering a given tier (de-escalating).
|
|
294
|
+
* `tier` is the tier we are *entering* on the way down.
|
|
295
|
+
*/
|
|
296
|
+
applyRestoration(tier) {
|
|
297
|
+
switch (tier) {
|
|
298
|
+
case MemoryTier.RED:
|
|
299
|
+
// Leaving CRITICAL → RED: restore emergency mode
|
|
300
|
+
if (this.emergencyModeActive) {
|
|
301
|
+
this.emergencyModeActive = false;
|
|
302
|
+
this.recordAction(tier, 'exit_emergency_mode');
|
|
303
|
+
}
|
|
304
|
+
break;
|
|
305
|
+
case MemoryTier.ORANGE:
|
|
306
|
+
// Leaving RED → ORANGE: restore all shed models in reverse order
|
|
307
|
+
this.restoreAllShedModels();
|
|
308
|
+
break;
|
|
309
|
+
case MemoryTier.YELLOW:
|
|
310
|
+
// Leaving ORANGE → YELLOW: restore FPS and federated learning
|
|
311
|
+
if (this.fpsReduced) {
|
|
312
|
+
this.fpsReduced = false;
|
|
313
|
+
this.callbacks.onRestoreSensingFps(this.normalFps);
|
|
314
|
+
this.recordAction(tier, `restore_fps_to_${this.normalFps}`);
|
|
315
|
+
}
|
|
316
|
+
if (this.federatedLearningDisabled) {
|
|
317
|
+
this.federatedLearningDisabled = false;
|
|
318
|
+
this.callbacks.onEnableFederatedLearning();
|
|
319
|
+
this.recordAction(tier, 'enable_federated_learning');
|
|
320
|
+
}
|
|
321
|
+
break;
|
|
322
|
+
case MemoryTier.GREEN:
|
|
323
|
+
// Leaving YELLOW → GREEN: restore cloud inference
|
|
324
|
+
if (this.cloudInferenceDisabled) {
|
|
325
|
+
this.cloudInferenceDisabled = false;
|
|
326
|
+
this.callbacks.onEnableCloudInference();
|
|
327
|
+
this.recordAction(tier, 'enable_cloud_inference');
|
|
328
|
+
}
|
|
329
|
+
this.callbacks.onRestoreNormal();
|
|
330
|
+
this.recordAction(tier, 'restore_normal');
|
|
331
|
+
break;
|
|
332
|
+
case MemoryTier.CRITICAL:
|
|
333
|
+
// No restoration for entering CRITICAL (only escalation)
|
|
334
|
+
break;
|
|
335
|
+
}
|
|
336
|
+
}
|
|
337
|
+
// ─── Model Shedding ───────────────────────────────────────────────────
|
|
338
|
+
/**
|
|
339
|
+
* Shed the next model in the shed order. Models are shed from the *end*
|
|
340
|
+
* of `shedOrder` (lowest priority) toward the beginning (highest priority).
|
|
341
|
+
* One model per call.
|
|
342
|
+
*/
|
|
343
|
+
shedNextModel() {
|
|
344
|
+
// Walk backwards from end of shedOrder, skipping already-shed models
|
|
345
|
+
for (let i = this.shedOrder.length - 1; i >= 0; i--) {
|
|
346
|
+
const model = this.shedOrder[i];
|
|
347
|
+
if (!this.shedModels.has(model)) {
|
|
348
|
+
this.shedModels.add(model);
|
|
349
|
+
this.callbacks.onShedModel(model);
|
|
350
|
+
this.recordAction(MemoryTier.RED, `shed_model_${model}`);
|
|
351
|
+
return;
|
|
352
|
+
}
|
|
353
|
+
}
|
|
354
|
+
// All models already shed — nothing more to do
|
|
355
|
+
}
|
|
356
|
+
/**
|
|
357
|
+
* Restore all shed models in reverse order (highest priority first,
|
|
358
|
+
* i.e., from the beginning of `shedOrder`).
|
|
359
|
+
*/
|
|
360
|
+
restoreAllShedModels() {
|
|
361
|
+
// Restore in forward order through shedOrder (most important first)
|
|
362
|
+
for (const model of this.shedOrder) {
|
|
363
|
+
if (this.shedModels.has(model)) {
|
|
364
|
+
this.shedModels.delete(model);
|
|
365
|
+
this.callbacks.onRestoreModel(model);
|
|
366
|
+
this.recordAction(MemoryTier.ORANGE, `restore_model_${model}`);
|
|
367
|
+
}
|
|
368
|
+
}
|
|
369
|
+
}
|
|
370
|
+
// ─── Snapshot / Recording ──────────────────────────────────────────────
|
|
371
|
+
takeSnapshot() {
|
|
372
|
+
const mem = process.memoryUsage();
|
|
373
|
+
const osTotalBytes = os.totalmem();
|
|
374
|
+
const osFreeBytes = os.freemem();
|
|
375
|
+
const osUsedBytes = osTotalBytes - osFreeBytes;
|
|
376
|
+
return {
|
|
377
|
+
heapUsedMb: Math.round((mem.heapUsed / MB) * 100) / 100,
|
|
378
|
+
heapTotalMb: Math.round((mem.heapTotal / MB) * 100) / 100,
|
|
379
|
+
heapUsedPercent: Math.round((mem.heapUsed / mem.heapTotal) * 10000) / 100,
|
|
380
|
+
rssUsedMb: Math.round((mem.rss / MB) * 100) / 100,
|
|
381
|
+
osFreeMemMb: Math.round((osFreeBytes / MB) * 100) / 100,
|
|
382
|
+
osTotalMemMb: Math.round((osTotalBytes / MB) * 100) / 100,
|
|
383
|
+
osUsedPercent: Math.round((osUsedBytes / osTotalBytes) * 10000) / 100,
|
|
384
|
+
tier: this.currentTier,
|
|
385
|
+
timestamp: Date.now(),
|
|
386
|
+
};
|
|
387
|
+
}
|
|
388
|
+
recordAction(tier, action) {
|
|
389
|
+
this.actions.push({
|
|
390
|
+
tier,
|
|
391
|
+
action,
|
|
392
|
+
timestamp: Date.now(),
|
|
393
|
+
});
|
|
394
|
+
if (this.actions.length > MAX_ACTIONS) {
|
|
395
|
+
this.actions.shift();
|
|
396
|
+
}
|
|
397
|
+
}
|
|
398
|
+
}
|
|
399
|
+
exports.MemoryAttenuationManager = MemoryAttenuationManager;
|
|
400
|
+
//# sourceMappingURL=MemoryAttenuationManager.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"MemoryAttenuationManager.js","sourceRoot":"","sources":["../src/MemoryAttenuationManager.ts"],"names":[],"mappings":"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"}
|