// memory-manager.js - 全局内存管理模块 // 全局内存管理对象 const memoryManager = { // 缓存管理 caches: { ipGeolocation: { data: new Map(), maxSize: 1000, order: [] }, domainInfo: { data: new Map(), maxSize: 500 }, apiResponses: { data: new Map(), maxSize: 100, ttl: 60000 // 1分钟过期 } }, // 资源管理 resources: { timers: [], eventListeners: [], webSockets: [], intervals: [] }, // 内存监控 monitoring: { enabled: true, history: [], maxHistory: 50, threshold: 80 // 内存使用阈值(%) }, // 初始化 init() { console.log('内存管理器初始化'); this.startMonitoring(); this.setupGlobalListeners(); }, // 启动内存监控 startMonitoring() { if (this.monitoring.enabled && performance && performance.memory) { setInterval(() => { this.checkMemoryUsage(); }, 30000); // 每30秒检查一次 } }, // 检查内存使用情况 checkMemoryUsage() { if (!performance || !performance.memory) return; const memory = performance.memory; const usage = { timestamp: Date.now(), used: Math.round(memory.usedJSHeapSize / 1024 / 1024 * 100) / 100, // MB total: Math.round(memory.totalJSHeapSize / 1024 / 1024 * 100) / 100, // MB limit: Math.round(memory.jsHeapSizeLimit / 1024 / 1024 * 100) / 100, // MB usagePercent: Math.round((memory.usedJSHeapSize / memory.jsHeapSizeLimit) * 100 * 100) / 100 // % }; this.monitoring.history.push(usage); // 限制历史记录大小 if (this.monitoring.history.length > this.monitoring.maxHistory) { this.monitoring.history.shift(); } // 内存使用过高时的处理 if (usage.usagePercent > this.monitoring.threshold) { console.warn('内存使用过高:', usage); this.triggerMemoryCleanup(); } console.log('内存使用情况:', usage); }, // 触发内存清理 triggerMemoryCleanup() { console.log('触发内存清理...'); // 清理缓存 this.cleanupCaches(); // 清理未使用的资源 this.cleanupUnusedResources(); }, // 清理缓存 cleanupCaches() { // 清理IP地理位置缓存 this.cleanupCache('ipGeolocation'); // 清理域名信息缓存 this.cleanupCache('domainInfo'); // 清理API响应缓存 this.cleanupCache('apiResponses'); }, // 清理特定缓存 cleanupCache(cacheName) { const cache = this.caches[cacheName]; if (!cache) return; console.log(`清理${cacheName}缓存 - 当前大小: ${cache.data.size}`); // 清理超出大小限制的缓存 if (cache.data.size > cache.maxSize) { if (cache.order && cache.order.length > 0) { // 使用LRU策略 while (cache.data.size > cache.maxSize && cache.order.length > 0) { const oldestKey = cache.order.shift(); if (oldestKey) { cache.data.delete(oldestKey); } } } else { // 简单清理(适用于有TTL的缓存) const now = Date.now(); for (const [key, value] of cache.data.entries()) { if (cache.data.size <= cache.maxSize) break; // 检查TTL if (cache.ttl && value.timestamp && (now - value.timestamp) > cache.ttl) { cache.data.delete(key); } } // 如果仍然超出大小限制,删除最旧的项 if (cache.data.size > cache.maxSize) { const keys = Array.from(cache.data.keys()); while (cache.data.size > cache.maxSize && keys.length > 0) { const oldestKey = keys.shift(); cache.data.delete(oldestKey); } } } } console.log(`清理后${cacheName}缓存大小: ${cache.data.size}`); }, // 清理未使用的资源 cleanupUnusedResources() { // 清理定时器(这里主要是记录,实际清理需要在具体组件中进行) console.log(`当前活动定时器数量: ${this.resources.timers.length}`); console.log(`当前活动事件监听器数量: ${this.resources.eventListeners.length}`); console.log(`当前活动WebSocket连接数量: ${this.resources.webSockets.length}`); console.log(`当前活动间隔定时器数量: ${this.resources.intervals.length}`); }, // 添加缓存项 addCacheItem(cacheName, key, value) { const cache = this.caches[cacheName]; if (!cache) return; // 检查缓存大小 if (cache.data.size >= cache.maxSize) { this.cleanupCache(cacheName); } // 添加到缓存 if (cache.ttl) { cache.data.set(key, { value, timestamp: Date.now() }); } else { cache.data.set(key, value); } // 更新访问顺序(用于LRU) if (cache.order) { // 移除现有的位置 const index = cache.order.indexOf(key); if (index > -1) { cache.order.splice(index, 1); } // 添加到末尾 cache.order.push(key); } }, // 获取缓存项 getCacheItem(cacheName, key) { const cache = this.caches[cacheName]; if (!cache) return null; const item = cache.data.get(key); if (!item) return null; // 检查TTL if (cache.ttl && item.timestamp && (Date.now() - item.timestamp) > cache.ttl) { cache.data.delete(key); return null; } // 更新访问顺序(用于LRU) if (cache.order) { // 移除现有的位置 const index = cache.order.indexOf(key); if (index > -1) { cache.order.splice(index, 1); } // 添加到末尾 cache.order.push(key); } return cache.ttl ? item.value : item; }, // 注册定时器 registerTimer(timerId) { if (timerId) { this.resources.timers.push(timerId); } }, // 注销定时器 unregisterTimer(timerId) { const index = this.resources.timers.indexOf(timerId); if (index > -1) { clearTimeout(timerId); this.resources.timers.splice(index, 1); } }, // 注册事件监听器 registerEventListener(element, event, handler) { if (element && event && handler) { this.resources.eventListeners.push({ element, event, handler }); } }, // 注销事件监听器 unregisterEventListener(element, event, handler) { const index = this.resources.eventListeners.findIndex(item => item.element === element && item.event === event && item.handler === handler ); if (index > -1) { element.removeEventListener(event, handler); this.resources.eventListeners.splice(index, 1); } }, // 注册WebSocket连接 registerWebSocket(ws) { if (ws) { this.resources.webSockets.push(ws); } }, // 注销WebSocket连接 unregisterWebSocket(ws) { const index = this.resources.webSockets.indexOf(ws); if (index > -1) { try { ws.close(); } catch (error) { console.error('关闭WebSocket连接失败:', error); } this.resources.webSockets.splice(index, 1); } }, // 注册间隔定时器 registerInterval(intervalId) { if (intervalId) { this.resources.intervals.push(intervalId); } }, // 注销间隔定时器 unregisterInterval(intervalId) { const index = this.resources.intervals.indexOf(intervalId); if (index > -1) { clearInterval(intervalId); this.resources.intervals.splice(index, 1); } }, // 清理所有资源 cleanupAllResources() { console.log('清理所有资源...'); // 清理定时器 this.resources.timers.forEach(timerId => { clearTimeout(timerId); }); this.resources.timers = []; // 清理事件监听器 this.resources.eventListeners.forEach(({ element, event, handler }) => { try { element.removeEventListener(event, handler); } catch (error) { console.error('移除事件监听器失败:', error); } }); this.resources.eventListeners = []; // 清理WebSocket连接 this.resources.webSockets.forEach(ws => { try { ws.close(); } catch (error) { console.error('关闭WebSocket连接失败:', error); } }); this.resources.webSockets = []; // 清理间隔定时器 this.resources.intervals.forEach(intervalId => { clearInterval(intervalId); }); this.resources.intervals = []; // 清理缓存 this.cleanupCaches(); console.log('所有资源已清理'); }, // 设置全局监听器 setupGlobalListeners() { // 页面卸载时清理所有资源 window.addEventListener('beforeunload', () => { this.cleanupAllResources(); }); // 页面可见性变化时的处理 document.addEventListener('visibilitychange', () => { if (document.hidden) { // 页面隐藏时清理一些资源 console.log('页面隐藏,清理资源...'); this.cleanupCaches(); } }); }, // 获取内存使用统计 getStats() { if (this.monitoring.history.length === 0) { return null; } const recent = this.monitoring.history[this.monitoring.history.length - 1]; const avg = this.monitoring.history.reduce((sum, item) => sum + item.used, 0) / this.monitoring.history.length; const max = Math.max(...this.monitoring.history.map(item => item.used)); const min = Math.min(...this.monitoring.history.map(item => item.used)); return { recent, avg: Math.round(avg * 100) / 100, max: Math.round(max * 100) / 100, min: Math.round(min * 100) / 100, history: this.monitoring.history, caches: { ipGeolocation: this.caches.ipGeolocation.data.size, domainInfo: this.caches.domainInfo.data.size, apiResponses: this.caches.apiResponses.data.size }, resources: { timers: this.resources.timers.length, eventListeners: this.resources.eventListeners.length, webSockets: this.resources.webSockets.length, intervals: this.resources.intervals.length } }; } }; // 导出内存管理器 if (typeof module !== 'undefined' && module.exports) { module.exports = memoryManager; } else { window.memoryManager = memoryManager; } // 自动初始化 if (typeof window !== 'undefined') { window.addEventListener('DOMContentLoaded', () => { memoryManager.init(); }); }