File size: 2,884 Bytes
ddce7e8
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
/**
 * 轻量定时内存清理器
 * - 不再基于内存占用/阈值判断(避免频繁扫描与 GC 抖动)
 * - 仅按时间间隔触发各模块的清理回调(对象池裁剪、缓存清理等)
 * @module utils/memoryManager
 */

import logger from './logger.js';

// 对象池最大大小(固定值,不再随“压力”动态变化)
const POOL_SIZES = { chunk: 30, toolCall: 15, lineBuffer: 5 };

class MemoryManager {
  constructor() {
    /** @type {Set<Function>} */
    this.cleanupCallbacks = new Set();
    /** @type {NodeJS.Timeout|null} */
    this.timer = null;
    /** @type {number} */
    this.cleanupIntervalMs = 30 * 60 * 1000;
    this.isShuttingDown = false;
  }

  /**
   * 启动定时清理
   * @param {number} cleanupIntervalMs - 清理间隔(毫秒)
   */
  start(cleanupIntervalMs = 30 * 60 * 1000) {
    if (this.timer) return;
    this.setCleanupInterval(cleanupIntervalMs);
    this.isShuttingDown = false;
    logger.info(`内存清理器已启动(间隔: ${Math.round(this.cleanupIntervalMs / 1000)}秒)`);
  }

  /**
   * 动态调整清理间隔(热更新)
   * @param {number} cleanupIntervalMs
   */
  setCleanupInterval(cleanupIntervalMs) {
    if (Number.isFinite(cleanupIntervalMs) && cleanupIntervalMs > 0) {
      this.cleanupIntervalMs = Math.floor(cleanupIntervalMs);
    }

    if (this.timer) {
      clearInterval(this.timer);
      this.timer = null;
    }

    this.timer = setInterval(() => {
      if (!this.isShuttingDown) this.cleanup('timer');
    }, this.cleanupIntervalMs);

    this.timer.unref?.();
  }

  /**
   * 停止定时清理
   */
  stop() {
    this.isShuttingDown = true;
    if (this.timer) {
      clearInterval(this.timer);
      this.timer = null;
    }
    this.cleanupCallbacks.clear();
    logger.info('内存清理器已停止');
  }

  /**
   * 注册清理回调
   * @param {(reason: string) => void} callback
   */
  registerCleanup(callback) {
    this.cleanupCallbacks.add(callback);
  }

  /**
   * 取消注册清理回调
   * @param {Function} callback
   */
  unregisterCleanup(callback) {
    this.cleanupCallbacks.delete(callback);
  }

  /**
   * 触发一次清理
   * @param {string} reason
   */
  cleanup(reason = 'manual') {
    for (const callback of this.cleanupCallbacks) {
      try {
        callback(reason);
      } catch (error) {
        logger.error('清理回调执行失败:', error.message);
      }
    }
  }

  /**
   * 获取对象池大小配置
   */
  getPoolSizes() {
    return POOL_SIZES;
  }
}

const memoryManager = new MemoryManager();
export default memoryManager;

// 统一封装:注册对象池裁剪(在定时清理触发时执行)
export function registerMemoryPoolCleanup(pool, getMaxSize) {
  memoryManager.registerCleanup(() => {
    const maxSize = getMaxSize();
    while (pool.length > maxSize) pool.pop();
  });
}