UNPKG

@lcap/nasl

Version:

NetEase Application Specific Language

267 lines 9.18 kB
"use strict"; /** * Memory optimization utilities for deployment data */ Object.defineProperty(exports, "__esModule", { value: true }); exports.smartDelay = exports.chunkLargeObject = exports.processInChunks = exports.compactAnnotatedJson = exports.resetOptimizationStats = exports.getOptimizationStats = exports.optimizeJsonDuringAnnotation = void 0; // 统计信息用于监控优化效果 let optimizationStats = { totalCalls: 0, propertiesRemoved: 0, emptyArraysRemoved: 0, undefinedValuesRemoved: 0 }; /** * 在标注过程中优化JSON对象,减少内存使用 * 这个函数专门用于集成到_toJSON过程中 */ function optimizeJsonDuringAnnotation(jsonObject) { if (!jsonObject || typeof jsonObject !== 'object') { return jsonObject; } optimizationStats.totalCalls++; // 要删除的属性列表 const propsToRemove = [ 'folded', 'offsetX', 'offsetY', // 'composedBy', 'silence', '_aiUID', // Vue reactive internals '__v_isRef', '__v_isReactive', '__v_isReadonly', '__v_isShallow', '__v_skip', '__v_raw', '_rawValue', '_shallow' ]; // 删除不需要的属性 propsToRemove.forEach(prop => { if (prop in jsonObject) { delete jsonObject[prop]; optimizationStats.propertiesRemoved++; } }); // 删除undefined Object.keys(jsonObject).forEach(key => { const value = jsonObject[key]; if (value === undefined) { delete jsonObject[key]; optimizationStats.undefinedValuesRemoved++; } }); return jsonObject; } exports.optimizeJsonDuringAnnotation = optimizeJsonDuringAnnotation; /** * 获取优化统计信息 */ function getOptimizationStats() { return { ...optimizationStats }; } exports.getOptimizationStats = getOptimizationStats; /** * 重置优化统计信息 */ function resetOptimizationStats() { optimizationStats = { totalCalls: 0, propertiesRemoved: 0, emptyArraysRemoved: 0, undefinedValuesRemoved: 0 }; } exports.resetOptimizationStats = resetOptimizationStats; /** * Removes additional unnecessary properties from annotated JSON to reduce size * * 注意:此函数用于独立的JSON压缩场景。 * 在主要的标注流程中,优化已经集成到了 optimizeJsonDuringAnnotation 中, * 以减少内存使用和处理时间。 * * 使用场景: * - 需要对已有的JSON对象进行后处理压缩 * - 第三方系统集成中需要压缩JSON数据 * - 测试和验证优化效果 */ function compactAnnotatedJson(annotatedJson) { if (!annotatedJson || typeof annotatedJson !== 'object') { return annotatedJson; } // Properties to remove for memory optimization const propsToRemove = new Set([ 'folded', 'offsetX', 'offsetY', 'staticStyle', 'display', 'composedBy', 'silence', '_aiUID', // Vue reactive internals '__v_isRef', '__v_isReactive', '__v_isReadonly', '__v_isShallow', '__v_skip', '__v_raw', '_rawValue', '_shallow', // Common circular reference properties 'parentNode', 'parentKey', 'app', 'naslServer', ]); // Track visited objects to prevent infinite recursion const visited = new WeakMap(); let visitId = 0; const compact = (obj, depth = 0) => { // Prevent deep recursion if (depth > 50) { return '[Max Depth Reached]'; } // Handle primitives and null if (obj === null || typeof obj !== 'object') { return obj; } // Handle circular references if (visited.has(obj)) { return `[Circular Reference: ${visited.get(obj)}]`; } const currentId = ++visitId; visited.set(obj, currentId); try { if (Array.isArray(obj)) { const result = []; for (let i = 0; i < obj.length; i++) { try { const item = obj[i]; if (item !== undefined) { result.push(compact(item, depth + 1)); } } catch (error) { // Skip problematic array items continue; } } return result; } // For objects, use a safer approach const result = {}; // Get own property names and descriptors to handle getters safely const propertyNames = Object.getOwnPropertyNames(obj); for (const key of propertyNames) { // Skip unwanted properties if (propsToRemove.has(key)) { continue; } // Skip internal/private properties if (key.startsWith('__') || key.startsWith('_') || key === 'constructor') { continue; } try { // Check if property is a getter/setter that might cause issues const descriptor = Object.getOwnPropertyDescriptor(obj, key); if (descriptor?.get && !descriptor.set) { // Skip getter-only properties as they might trigger Vue reactivity continue; } const value = obj[key]; // Skip functions, symbols, and undefined if (typeof value === 'function' || typeof value === 'symbol' || value === undefined) { continue; } // Skip empty arrays to reduce size if (Array.isArray(value) && value.length === 0) { continue; } // Recursively compact the value result[key] = compact(value, depth + 1); } catch (error) { // Skip properties that throw errors when accessed continue; } } return result; } catch (error) { // If all else fails, try JSON.parse(JSON.stringify()) for safe serialization try { return JSON.parse(JSON.stringify(obj)); } catch (jsonError) { return '[Serialization Error]'; } } finally { // Clean up visited tracking for this object visited.delete(obj); } }; try { console.time('JSON Compaction'); const result = compact(annotatedJson); console.timeEnd('JSON Compaction'); return result; } catch (error) { console.warn('JSON compaction failed, using JSON.stringify fallback:', error); // Safe fallback using native JSON serialization try { return JSON.parse(JSON.stringify(annotatedJson)); } catch (fallbackError) { console.error('Even JSON.stringify fallback failed:', fallbackError); return annotatedJson; } } } exports.compactAnnotatedJson = compactAnnotatedJson; /** * Processes large objects in chunks to avoid memory spikes */ async function processInChunks(items, processor, chunkSize = 100) { const results = []; for (let i = 0; i < items.length; i += chunkSize) { const chunk = items.slice(i, i + chunkSize); const chunkResults = await processor(chunk); results.push(...chunkResults); // Allow garbage collection between chunks if (i % (chunkSize * 5) === 0) { await new Promise(resolve => setTimeout(resolve, 1)); } } return results; } exports.processInChunks = processInChunks; /** * Splits large objects into smaller chunks for processing */ function chunkLargeObject(obj, maxSize = 50) { const entries = Object.entries(obj); const chunks = []; for (let i = 0; i < entries.length; i += maxSize) { const chunkEntries = entries.slice(i, i + maxSize); const chunk = Object.fromEntries(chunkEntries); chunks.push(chunk); } return chunks; } exports.chunkLargeObject = chunkLargeObject; /** * Memory-aware delay function that considers current memory usage */ async function smartDelay(baseDelay = 10) { // Check memory usage if available const memory = performance?.memory; if (memory) { const usageRatio = memory.usedJSHeapSize / memory.jsHeapSizeLimit; // If memory usage is high, delay longer to allow GC const adjustedDelay = usageRatio > 0.8 ? baseDelay * 3 : usageRatio > 0.6 ? baseDelay * 2 : baseDelay; await new Promise(resolve => setTimeout(resolve, adjustedDelay)); } else { await new Promise(resolve => setTimeout(resolve, baseDelay)); } } exports.smartDelay = smartDelay; //# sourceMappingURL=memory-optimization.js.map