Download src/utils/memoryManager.js from ASEM12345/anti_api: direct link, hf CLI and curl.
- Browser
- Download file 8.59 kB
-
https://huggingface.co/spaces/ASEM12345/anti_api/resolve/main/src/utils/memoryManager.js
- Command line
-
hf download hf://spaces/ASEM12345/anti_api/src/utils/memoryManager.js
-
curl -L -o memoryManager.js https://huggingface.co/spaces/ASEM12345/anti_api/resolve/main/src/utils/memoryManager.js
8.59 kB
| /** | |
| * 智能内存管理器 | |
| * 采用分级策略,根据内存压力动态调整缓存和对象池 | |
| * 阈值基于用户配置的 memoryThreshold(MB)动态计算 | |
| * @module utils/memoryManager | |
| */ | |
| import logger from './logger.js'; | |
| import { GC_COOLDOWN } from '../constants/index.js'; | |
| /** | |
| * 内存压力级别枚举 | |
| * @enum {string} | |
| */ | |
| const MemoryPressure = { | |
| LOW: 'low', // < 30% 阈值 - 正常运行 | |
| MEDIUM: 'medium', // 30%-60% 阈值 - 轻度清理 | |
| HIGH: 'high', // 60%-100% 阈值 - 积极清理 | |
| CRITICAL: 'critical' // > 100% 阈值 - 紧急清理 | |
| }; | |
| /** | |
| * 根据用户配置的内存阈值计算各级别阈值 | |
| * @param {number} thresholdMB - 用户配置的内存阈值(MB),即高压力阈值 | |
| * @returns {Object} 各级别阈值(字节) | |
| */ | |
| function calculateThresholds(thresholdMB) { | |
| const highBytes = thresholdMB * 1024 * 1024; | |
| return { | |
| LOW: Math.floor(highBytes * 0.3), // 30% 为低压力阈值 | |
| MEDIUM: Math.floor(highBytes * 0.6), // 60% 为中等压力阈值 | |
| HIGH: highBytes, // 100% 为高压力阈值(用户配置值) | |
| TARGET: Math.floor(highBytes * 0.5) // 50% 为目标内存 | |
| }; | |
| } | |
| // 默认阈值(100MB),会在初始化时被配置覆盖 | |
| let THRESHOLDS = calculateThresholds(100); | |
| // 对象池最大大小配置(根据压力调整) | |
| const POOL_SIZES = { | |
| [MemoryPressure.LOW]: { chunk: 30, toolCall: 15, lineBuffer: 5 }, | |
| [MemoryPressure.MEDIUM]: { chunk: 20, toolCall: 10, lineBuffer: 3 }, | |
| [MemoryPressure.HIGH]: { chunk: 10, toolCall: 5, lineBuffer: 2 }, | |
| [MemoryPressure.CRITICAL]: { chunk: 5, toolCall: 3, lineBuffer: 1 } | |
| }; | |
| /** | |
| * 内存管理器类 | |
| */ | |
| class MemoryManager { | |
| constructor() { | |
| /** @type {string} */ | |
| this.currentPressure = MemoryPressure.LOW; | |
| /** @type {Set<Function>} */ | |
| this.cleanupCallbacks = new Set(); | |
| /** @type {number} */ | |
| this.lastGCTime = 0; | |
| /** @type {number} */ | |
| this.gcCooldown = GC_COOLDOWN; | |
| this.checkInterval = null; | |
| this.isShuttingDown = false; | |
| /** @type {number} 用户配置的内存阈值(MB) */ | |
| this.configuredThresholdMB = 100; | |
| // 统计信息 | |
| this.stats = { | |
| gcCount: 0, | |
| cleanupCount: 0, | |
| peakMemory: 0 | |
| }; | |
| } | |
| /** | |
| * 设置内存阈值(从配置加载) | |
| * @param {number} thresholdMB - 内存阈值(MB) | |
| */ | |
| setThreshold(thresholdMB) { | |
| if (thresholdMB && thresholdMB > 0) { | |
| this.configuredThresholdMB = thresholdMB; | |
| THRESHOLDS = calculateThresholds(thresholdMB); | |
| logger.info(`内存阈值已设置: ${thresholdMB}MB (LOW: ${Math.floor(THRESHOLDS.LOW/1024/1024)}MB, MEDIUM: ${Math.floor(THRESHOLDS.MEDIUM/1024/1024)}MB, HIGH: ${Math.floor(THRESHOLDS.HIGH/1024/1024)}MB)`); | |
| } | |
| } | |
| /** | |
| * 获取当前阈值配置 | |
| */ | |
| getThresholds() { | |
| return { | |
| configuredMB: this.configuredThresholdMB, | |
| lowMB: Math.floor(THRESHOLDS.LOW / 1024 / 1024), | |
| mediumMB: Math.floor(THRESHOLDS.MEDIUM / 1024 / 1024), | |
| highMB: Math.floor(THRESHOLDS.HIGH / 1024 / 1024), | |
| targetMB: Math.floor(THRESHOLDS.TARGET / 1024 / 1024) | |
| }; | |
| } | |
| /** | |
| * 启动内存监控 | |
| * @param {number} interval - 检查间隔(毫秒) | |
| */ | |
| start(interval = 30000) { | |
| if (this.checkInterval) return; | |
| this.checkInterval = setInterval(() => { | |
| if (!this.isShuttingDown) { | |
| this.check(); | |
| } | |
| }, interval); | |
| // 首次立即检查 | |
| this.check(); | |
| logger.info(`内存管理器已启动 (检查间隔: ${interval/1000}秒)`); | |
| } | |
| /** | |
| * 停止内存监控 | |
| */ | |
| stop() { | |
| this.isShuttingDown = true; | |
| if (this.checkInterval) { | |
| clearInterval(this.checkInterval); | |
| this.checkInterval = null; | |
| } | |
| this.cleanupCallbacks.clear(); | |
| logger.info('内存管理器已停止'); | |
| } | |
| /** | |
| * 注册清理回调 | |
| * @param {Function} callback - 清理函数,接收 pressure 参数 | |
| */ | |
| registerCleanup(callback) { | |
| this.cleanupCallbacks.add(callback); | |
| } | |
| /** | |
| * 取消注册清理回调 | |
| * @param {Function} callback | |
| */ | |
| unregisterCleanup(callback) { | |
| this.cleanupCallbacks.delete(callback); | |
| } | |
| /** | |
| * 获取当前内存使用情况 | |
| */ | |
| getMemoryUsage() { | |
| const usage = process.memoryUsage(); | |
| return { | |
| heapUsed: usage.heapUsed, | |
| heapTotal: usage.heapTotal, | |
| rss: usage.rss, | |
| external: usage.external, | |
| heapUsedMB: Math.round(usage.heapUsed / 1024 / 1024 * 10) / 10 | |
| }; | |
| } | |
| /** | |
| * 确定内存压力级别 | |
| */ | |
| getPressureLevel(heapUsed) { | |
| if (heapUsed < THRESHOLDS.LOW) return MemoryPressure.LOW; | |
| if (heapUsed < THRESHOLDS.MEDIUM) return MemoryPressure.MEDIUM; | |
| if (heapUsed < THRESHOLDS.HIGH) return MemoryPressure.HIGH; | |
| return MemoryPressure.CRITICAL; | |
| } | |
| /** | |
| * 获取当前压力下的对象池大小配置 | |
| */ | |
| getPoolSizes() { | |
| return POOL_SIZES[this.currentPressure]; | |
| } | |
| /** | |
| * 获取当前压力级别 | |
| */ | |
| getCurrentPressure() { | |
| return this.currentPressure; | |
| } | |
| /** | |
| * 检查内存并触发相应清理 | |
| */ | |
| check() { | |
| const { heapUsed, heapUsedMB } = this.getMemoryUsage(); | |
| const newPressure = this.getPressureLevel(heapUsed); | |
| // 更新峰值统计 | |
| if (heapUsed > this.stats.peakMemory) { | |
| this.stats.peakMemory = heapUsed; | |
| } | |
| // 压力级别变化时记录日志 | |
| if (newPressure !== this.currentPressure) { | |
| logger.info(`内存压力变化: ${this.currentPressure} -> ${newPressure} (${heapUsedMB}MB)`); | |
| this.currentPressure = newPressure; | |
| } | |
| // 根据压力级别执行不同策略 | |
| switch (newPressure) { | |
| case MemoryPressure.CRITICAL: | |
| this.handleCriticalPressure(heapUsedMB); | |
| break; | |
| case MemoryPressure.HIGH: | |
| this.handleHighPressure(heapUsedMB); | |
| break; | |
| case MemoryPressure.MEDIUM: | |
| this.handleMediumPressure(heapUsedMB); | |
| break; | |
| // LOW 压力不需要特殊处理 | |
| } | |
| return newPressure; | |
| } | |
| /** | |
| * 处理中等压力 | |
| */ | |
| handleMediumPressure(heapUsedMB) { | |
| // 通知各模块缩减对象池 | |
| this.notifyCleanup(MemoryPressure.MEDIUM); | |
| this.stats.cleanupCount++; | |
| } | |
| /** | |
| * 处理高压力 | |
| */ | |
| handleHighPressure(heapUsedMB) { | |
| logger.info(`内存较高 (${heapUsedMB}MB),执行积极清理`); | |
| this.notifyCleanup(MemoryPressure.HIGH); | |
| this.stats.cleanupCount++; | |
| // 尝试触发 GC(带冷却) | |
| this.tryGC(); | |
| } | |
| /** | |
| * 处理紧急压力 | |
| */ | |
| handleCriticalPressure(heapUsedMB) { | |
| logger.warn(`内存紧急 (${heapUsedMB}MB),执行紧急清理`); | |
| this.notifyCleanup(MemoryPressure.CRITICAL); | |
| this.stats.cleanupCount++; | |
| // 强制 GC(忽略冷却) | |
| this.forceGC(); | |
| } | |
| /** | |
| * 通知所有注册的清理回调 | |
| */ | |
| notifyCleanup(pressure) { | |
| for (const callback of this.cleanupCallbacks) { | |
| try { | |
| callback(pressure); | |
| } catch (error) { | |
| logger.error('清理回调执行失败:', error.message); | |
| } | |
| } | |
| } | |
| /** | |
| * 尝试触发 GC(带冷却时间) | |
| */ | |
| tryGC() { | |
| const now = Date.now(); | |
| if (now - this.lastGCTime < this.gcCooldown) { | |
| return false; | |
| } | |
| return this.forceGC(); | |
| } | |
| /** | |
| * 强制触发 GC | |
| */ | |
| forceGC() { | |
| if (global.gc) { | |
| const before = this.getMemoryUsage().heapUsedMB; | |
| global.gc(); | |
| this.lastGCTime = Date.now(); | |
| this.stats.gcCount++; | |
| const after = this.getMemoryUsage().heapUsedMB; | |
| logger.info(`GC 完成: ${before}MB -> ${after}MB (释放 ${(before - after).toFixed(1)}MB)`); | |
| return true; | |
| } | |
| return false; | |
| } | |
| /** | |
| * 手动触发检查和清理 | |
| */ | |
| cleanup() { | |
| return this.check(); | |
| } | |
| /** | |
| * 获取统计信息 | |
| */ | |
| getStats() { | |
| const memory = this.getMemoryUsage(); | |
| return { | |
| ...this.stats, | |
| currentPressure: this.currentPressure, | |
| currentHeapMB: memory.heapUsedMB, | |
| peakMemoryMB: Math.round(this.stats.peakMemory / 1024 / 1024 * 10) / 10, | |
| poolSizes: this.getPoolSizes(), | |
| thresholds: this.getThresholds() | |
| }; | |
| } | |
| } | |
| // 单例导出 | |
| const memoryManager = new MemoryManager(); | |
| export default memoryManager; | |
| // 统一封装注册清理回调,方便在各模块中保持一致风格 | |
| export function registerMemoryPoolCleanup(pool, getMaxSize) { | |
| memoryManager.registerCleanup(() => { | |
| const maxSize = getMaxSize(); | |
| while (pool.length > maxSize) { | |
| pool.pop(); | |
| } | |
| }); | |
| } | |
| export { MemoryPressure, THRESHOLDS }; |