@lcap/nasl
Version:
NetEase Application Specific Language
267 lines • 9.18 kB
JavaScript
;
/**
* 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