9.1 性能优化概述
9.1.1 性能优化的重要性
Sciter应用的性能直接影响用户体验,良好的性能优化可以:
- 提升响应速度:减少界面卡顿和延迟
- 降低资源消耗:减少内存和CPU使用
- 改善用户体验:提供流畅的交互体验
- 扩展应用规模:支持更复杂的功能和更多数据
9.1.2 性能瓶颈分析
// 性能监控工具
namespace PerformanceMonitor {
var metrics = {
renderTime: [],
scriptTime: [],
memoryUsage: [],
domNodes: [],
eventHandlers: 0
};
var isMonitoring = false;
var monitoringInterval = null;
// 开始性能监控
function startMonitoring(interval = 1000) {
if (isMonitoring) {
return {
success: false,
error: '性能监控已在运行'
};
}
isMonitoring = true;
monitoringInterval = setInterval(function() {
collectMetrics();
}, interval);
stdout.println('性能监控已启动,采样间隔:', interval + 'ms');
return {
success: true,
interval: interval
};
}
// 停止性能监控
function stopMonitoring() {
if (!isMonitoring) {
return {
success: false,
error: '性能监控未运行'
};
}
isMonitoring = false;
if (monitoringInterval) {
clearInterval(monitoringInterval);
monitoringInterval = null;
}
stdout.println('性能监控已停止');
return {
success: true,
metrics: getMetricsSummary()
};
}
// 收集性能指标
function collectMetrics() {
try {
// 获取渲染时间
var renderStart = Date.now();
view.update(); // 强制重绘
var renderTime = Date.now() - renderStart;
// 获取内存使用情况
var memoryInfo = System.memory.getUsage();
// 获取DOM节点数量
var domNodeCount = document.querySelectorAll('*').length;
// 记录指标
metrics.renderTime.push({
timestamp: Date.now(),
value: renderTime
});
metrics.memoryUsage.push({
timestamp: Date.now(),
value: memoryInfo.used
});
metrics.domNodes.push({
timestamp: Date.now(),
value: domNodeCount
});
// 限制历史数据长度
var maxHistory = 100;
if (metrics.renderTime.length > maxHistory) {
metrics.renderTime.shift();
metrics.memoryUsage.shift();
metrics.domNodes.shift();
}
} catch (error) {
stdout.println('收集性能指标时出错:', error.message);
}
}
// 获取性能指标摘要
function getMetricsSummary() {
function calculateStats(data) {
if (data.length === 0) return null;
var values = data.map(item => item.value);
var sum = values.reduce((a, b) => a + b, 0);
var avg = sum / values.length;
var min = Math.min(...values);
var max = Math.max(...values);
return {
count: values.length,
average: avg,
minimum: min,
maximum: max,
latest: values[values.length - 1]
};
}
return {
renderTime: calculateStats(metrics.renderTime),
memoryUsage: calculateStats(metrics.memoryUsage),
domNodes: calculateStats(metrics.domNodes),
eventHandlers: metrics.eventHandlers,
isMonitoring: isMonitoring
};
}
// 性能警告检查
function checkPerformanceWarnings() {
var warnings = [];
var summary = getMetricsSummary();
// 检查渲染时间
if (summary.renderTime && summary.renderTime.average > 16) {
warnings.push({
type: 'render',
severity: 'high',
message: `平均渲染时间过长: ${summary.renderTime.average.toFixed(2)}ms (建议 < 16ms)`,
suggestion: '考虑减少DOM复杂度或优化CSS'
});
}
// 检查内存使用
if (summary.memoryUsage && summary.memoryUsage.latest > 100 * 1024 * 1024) {
warnings.push({
type: 'memory',
severity: 'medium',
message: `内存使用过高: ${(summary.memoryUsage.latest / 1024 / 1024).toFixed(2)}MB`,
suggestion: '检查内存泄漏或减少数据缓存'
});
}
// 检查DOM节点数量
if (summary.domNodes && summary.domNodes.latest > 1000) {
warnings.push({
type: 'dom',
severity: 'medium',
message: `DOM节点过多: ${summary.domNodes.latest}个`,
suggestion: '考虑虚拟化长列表或简化DOM结构'
});
}
return {
warnings: warnings,
warningCount: warnings.length,
hasHighSeverity: warnings.some(w => w.severity === 'high')
};
}
// 生成性能报告
function generateReport() {
var summary = getMetricsSummary();
var warnings = checkPerformanceWarnings();
var report = {
timestamp: new Date().toISOString(),
summary: summary,
warnings: warnings,
recommendations: []
};
// 生成优化建议
if (summary.renderTime && summary.renderTime.average > 10) {
report.recommendations.push('优化CSS选择器和动画性能');
}
if (summary.domNodes && summary.domNodes.latest > 500) {
report.recommendations.push('考虑使用虚拟滚动或分页加载');
}
if (warnings.warningCount > 0) {
report.recommendations.push('解决性能警告中的问题');
}
return report;
}
// 导出性能数据
function exportMetrics(format = 'json') {
var data = {
metrics: metrics,
summary: getMetricsSummary(),
warnings: checkPerformanceWarnings(),
exportTime: new Date().toISOString()
};
switch (format) {
case 'json':
return JSON.stringify(data, null, 2);
case 'csv':
var csv = 'Timestamp,RenderTime,MemoryUsage,DOMNodes\n';
var maxLength = Math.max(
metrics.renderTime.length,
metrics.memoryUsage.length,
metrics.domNodes.length
);
for (var i = 0; i < maxLength; i++) {
var renderTime = metrics.renderTime[i] || { timestamp: '', value: '' };
var memoryUsage = metrics.memoryUsage[i] || { timestamp: '', value: '' };
var domNodes = metrics.domNodes[i] || { timestamp: '', value: '' };
csv += `${renderTime.timestamp},${renderTime.value},${memoryUsage.value},${domNodes.value}\n`;
}
return csv;
default:
return data;
}
}
}
9.2 DOM性能优化
9.2.1 DOM操作优化
// DOM操作优化工具
namespace DOMOptimizer {
// 批量DOM操作
class BatchDOMUpdater {
function this() {
this.operations = [];
this.isUpdating = false;
}
// 添加操作到批次
function addOperation(type, element, data) {
this.operations.push({
type: type,
element: element,
data: data,
timestamp: Date.now()
});
if (!this.isUpdating) {
this.scheduleUpdate();
}
}
// 调度更新
function scheduleUpdate() {
this.isUpdating = true;
// 使用requestAnimationFrame确保在下一帧执行
requestAnimationFrame(() => {
this.executeBatch();
this.isUpdating = false;
});
}
// 执行批量操作
function executeBatch() {
if (this.operations.length === 0) return;
var startTime = Date.now();
// 按类型分组操作
var groupedOps = {};
for (var op of this.operations) {
if (!groupedOps[op.type]) {
groupedOps[op.type] = [];
}
groupedOps[op.type].push(op);
}
// 执行分组操作
for (var [type, ops] of Object.entries(groupedOps)) {
this.executeOperationType(type, ops);
}
var executionTime = Date.now() - startTime;
stdout.println(`批量DOM操作完成: ${this.operations.length}个操作,耗时${executionTime}ms`);
// 清空操作队列
this.operations = [];
}
// 执行特定类型的操作
function executeOperationType(type, operations) {
switch (type) {
case 'addClass':
for (var op of operations) {
op.element.classList.add(op.data);
}
break;
case 'removeClass':
for (var op of operations) {
op.element.classList.remove(op.data);
}
break;
case 'setAttribute':
for (var op of operations) {
op.element.setAttribute(op.data.name, op.data.value);
}
break;
case 'setStyle':
for (var op of operations) {
op.element.style[op.data.property] = op.data.value;
}
break;
case 'setContent':
for (var op of operations) {
op.element.innerHTML = op.data;
}
break;
case 'appendChild':
for (var op of operations) {
op.element.appendChild(op.data);
}
break;
case 'removeChild':
for (var op of operations) {
if (op.data.parentNode) {
op.data.parentNode.removeChild(op.data);
}
}
break;
}
}
// 便捷方法
function addClass(element, className) {
this.addOperation('addClass', element, className);
}
function removeClass(element, className) {
this.addOperation('removeClass', element, className);
}
function setAttribute(element, name, value) {
this.addOperation('setAttribute', element, { name: name, value: value });
}
function setStyle(element, property, value) {
this.addOperation('setStyle', element, { property: property, value: value });
}
function setContent(element, content) {
this.addOperation('setContent', element, content);
}
function appendChild(parent, child) {
this.addOperation('appendChild', parent, child);
}
function removeChild(child) {
this.addOperation('removeChild', null, child);
}
}
// 虚拟滚动实现
class VirtualScroller {
function this(container, options = {}) {
this.container = container;
this.itemHeight = options.itemHeight || 40;
this.bufferSize = options.bufferSize || 5;
this.data = [];
this.renderFunction = options.renderFunction || this.defaultRenderFunction;
this.scrollTop = 0;
this.containerHeight = 0;
this.visibleStart = 0;
this.visibleEnd = 0;
this.init();
}
// 初始化
function init() {
this.container.style.overflow = 'auto';
this.container.style.position = 'relative';
// 创建内容容器
this.contentContainer = document.createElement('div');
this.contentContainer.style.position = 'relative';
this.container.appendChild(this.contentContainer);
// 绑定滚动事件
this.container.addEventListener('scroll', (event) => {
this.handleScroll();
});
// 监听容器大小变化
this.updateContainerHeight();
}
// 设置数据
function setData(data) {
this.data = data;
this.updateVirtualHeight();
this.render();
}
// 更新虚拟高度
function updateVirtualHeight() {
var totalHeight = this.data.length * this.itemHeight;
this.contentContainer.style.height = totalHeight + 'px';
}
// 更新容器高度
function updateContainerHeight() {
this.containerHeight = this.container.clientHeight;
}
// 处理滚动
function handleScroll() {
this.scrollTop = this.container.scrollTop;
this.calculateVisibleRange();
this.render();
}
// 计算可见范围
function calculateVisibleRange() {
var startIndex = Math.floor(this.scrollTop / this.itemHeight);
var endIndex = Math.min(
startIndex + Math.ceil(this.containerHeight / this.itemHeight),
this.data.length - 1
);
// 添加缓冲区
this.visibleStart = Math.max(0, startIndex - this.bufferSize);
this.visibleEnd = Math.min(this.data.length - 1, endIndex + this.bufferSize);
}
// 渲染可见项目
function render() {
// 清空现有内容
this.contentContainer.innerHTML = '';
// 渲染可见项目
for (var i = this.visibleStart; i <= this.visibleEnd; i++) {
var item = this.data[i];
var element = this.renderFunction(item, i);
// 设置位置
element.style.position = 'absolute';
element.style.top = (i * this.itemHeight) + 'px';
element.style.height = this.itemHeight + 'px';
element.style.width = '100%';
this.contentContainer.appendChild(element);
}
}
// 默认渲染函数
function defaultRenderFunction(item, index) {
var div = document.createElement('div');
div.textContent = typeof item === 'string' ? item : JSON.stringify(item);
div.style.padding = '10px';
div.style.borderBottom = '1px solid #eee';
return div;
}
// 滚动到指定项目
function scrollToItem(index) {
var targetScrollTop = index * this.itemHeight;
this.container.scrollTop = targetScrollTop;
}
// 获取当前可见项目
function getVisibleItems() {
return this.data.slice(this.visibleStart, this.visibleEnd + 1);
}
// 更新单个项目
function updateItem(index, newData) {
if (index >= 0 && index < this.data.length) {
this.data[index] = newData;
// 如果项目在可见范围内,重新渲染
if (index >= this.visibleStart && index <= this.visibleEnd) {
this.render();
}
}
}
// 销毁
function destroy() {
this.container.removeEventListener('scroll', this.handleScroll);
this.container.innerHTML = '';
}
}
// DOM查询优化
class DOMQueryOptimizer {
function this() {
this.cache = new Map();
this.cacheTimeout = 5000; // 5秒缓存
}
// 缓存查询结果
function querySelector(selector, useCache = true) {
if (!useCache) {
return document.querySelector(selector);
}
var cacheKey = 'single:' + selector;
var cached = this.cache.get(cacheKey);
if (cached && Date.now() - cached.timestamp < this.cacheTimeout) {
return cached.result;
}
var result = document.querySelector(selector);
this.cache.set(cacheKey, {
result: result,
timestamp: Date.now()
});
return result;
}
// 缓存查询所有结果
function querySelectorAll(selector, useCache = true) {
if (!useCache) {
return document.querySelectorAll(selector);
}
var cacheKey = 'all:' + selector;
var cached = this.cache.get(cacheKey);
if (cached && Date.now() - cached.timestamp < this.cacheTimeout) {
return cached.result;
}
var result = document.querySelectorAll(selector);
this.cache.set(cacheKey, {
result: result,
timestamp: Date.now()
});
return result;
}
// 清除缓存
function clearCache() {
this.cache.clear();
}
// 清除过期缓存
function clearExpiredCache() {
var now = Date.now();
for (var [key, value] of this.cache) {
if (now - value.timestamp >= this.cacheTimeout) {
this.cache.delete(key);
}
}
}
// 获取缓存统计
function getCacheStats() {
return {
size: this.cache.size,
timeout: this.cacheTimeout
};
}
}
}
// 使用示例
function domOptimizationExample() {
// 批量DOM更新示例
var batchUpdater = new DOMOptimizer.BatchDOMUpdater();
var elements = document.querySelectorAll('.item');
for (var element of elements) {
batchUpdater.addClass(element, 'active');
batchUpdater.setStyle(element, 'opacity', '0.8');
}
// 虚拟滚动示例
var container = document.querySelector('#scroll-container');
var virtualScroller = new DOMOptimizer.VirtualScroller(container, {
itemHeight: 50,
bufferSize: 3,
renderFunction: function(item, index) {
var div = document.createElement('div');
div.innerHTML = `<div class="item-${index}">${item.name}</div>`;
return div;
}
});
// 设置大量数据
var largeDataSet = [];
for (var i = 0; i < 10000; i++) {
largeDataSet.push({ name: `项目 ${i}`, value: i });
}
virtualScroller.setData(largeDataSet);
// DOM查询优化示例
var queryOptimizer = new DOMOptimizer.DOMQueryOptimizer();
// 使用缓存查询
var header = queryOptimizer.querySelector('#header');
var menuItems = queryOptimizer.querySelectorAll('.menu-item');
stdout.println('DOM优化示例完成');
}
9.2.2 CSS性能优化
// CSS性能优化工具
namespace CSSOptimizer {
// CSS动画优化
class AnimationOptimizer {
function this() {
this.activeAnimations = new Map();
this.animationFrame = null;
}
// 创建高性能动画
function createAnimation(element, properties, options = {}) {
var {
duration = 300,
easing = 'ease-out',
onComplete = null,
useTransform = true
} = options;
var animationId = 'anim_' + Date.now() + '_' + Math.random();
var animation = {
id: animationId,
element: element,
properties: properties,
duration: duration,
easing: easing,
startTime: null,
onComplete: onComplete,
useTransform: useTransform
};
this.activeAnimations.set(animationId, animation);
if (!this.animationFrame) {
this.startAnimationLoop();
}
return animationId;
}
// 启动动画循环
function startAnimationLoop() {
this.animationFrame = requestAnimationFrame(() => {
this.updateAnimations();
if (this.activeAnimations.size > 0) {
this.startAnimationLoop();
} else {
this.animationFrame = null;
}
});
}
// 更新动画
function updateAnimations() {
var currentTime = Date.now();
var completedAnimations = [];
for (var [id, animation] of this.activeAnimations) {
if (!animation.startTime) {
animation.startTime = currentTime;
}
var elapsed = currentTime - animation.startTime;
var progress = Math.min(elapsed / animation.duration, 1);
// 应用缓动函数
var easedProgress = this.applyEasing(progress, animation.easing);
// 更新属性
this.updateAnimationProperties(animation, easedProgress);
// 检查动画是否完成
if (progress >= 1) {
completedAnimations.push(id);
if (animation.onComplete) {
animation.onComplete();
}
}
}
// 移除完成的动画
for (var id of completedAnimations) {
this.activeAnimations.delete(id);
}
}
// 更新动画属性
function updateAnimationProperties(animation, progress) {
var element = animation.element;
var properties = animation.properties;
if (animation.useTransform && this.canUseTransform(properties)) {
// 使用transform优化
var transforms = [];
for (var [prop, value] of Object.entries(properties)) {
var currentValue = this.interpolateValue(prop, 0, value, progress);
switch (prop) {
case 'x':
case 'translateX':
transforms.push(`translateX(${currentValue}px)`);
break;
case 'y':
case 'translateY':
transforms.push(`translateY(${currentValue}px)`);
break;
case 'scale':
transforms.push(`scale(${currentValue})`);
break;
case 'rotate':
transforms.push(`rotate(${currentValue}deg)`);
break;
}
}
if (transforms.length > 0) {
element.style.transform = transforms.join(' ');
}
} else {
// 使用常规CSS属性
for (var [prop, value] of Object.entries(properties)) {
var currentValue = this.interpolateValue(prop, 0, value, progress);
element.style[prop] = currentValue + this.getUnit(prop);
}
}
}
// 检查是否可以使用transform
function canUseTransform(properties) {
var transformProps = ['x', 'y', 'translateX', 'translateY', 'scale', 'rotate'];
return Object.keys(properties).some(prop => transformProps.includes(prop));
}
// 插值计算
function interpolateValue(property, start, end, progress) {
return start + (end - start) * progress;
}
// 获取CSS单位
function getUnit(property) {
var pixelProps = ['width', 'height', 'top', 'left', 'right', 'bottom', 'margin', 'padding'];
return pixelProps.includes(property) ? 'px' : '';
}
// 应用缓动函数
function applyEasing(progress, easing) {
switch (easing) {
case 'linear':
return progress;
case 'ease-in':
return progress * progress;
case 'ease-out':
return 1 - Math.pow(1 - progress, 2);
case 'ease-in-out':
return progress < 0.5 ?
2 * progress * progress :
1 - Math.pow(-2 * progress + 2, 2) / 2;
default:
return progress;
}
}
// 停止动画
function stopAnimation(animationId) {
if (this.activeAnimations.has(animationId)) {
this.activeAnimations.delete(animationId);
return true;
}
return false;
}
// 停止所有动画
function stopAllAnimations() {
this.activeAnimations.clear();
if (this.animationFrame) {
cancelAnimationFrame(this.animationFrame);
this.animationFrame = null;
}
}
// 获取活动动画数量
function getActiveAnimationCount() {
return this.activeAnimations.size;
}
}
// CSS规则优化
class StyleOptimizer {
function this() {
this.styleCache = new Map();
this.computedStyleCache = new Map();
}
// 批量应用样式
function applyStyles(element, styles) {
// 使用cssText一次性应用所有样式
var cssText = '';
for (var [property, value] of Object.entries(styles)) {
cssText += `${this.kebabCase(property)}: ${value}; `;
}
element.style.cssText += cssText;
}
// 驼峰转短横线
function kebabCase(str) {
return str.replace(/([a-z0-9])([A-Z])/g, '$1-$2').toLowerCase();
}
// 缓存计算样式
function getComputedStyle(element, property, useCache = true) {
if (!useCache) {
return window.getComputedStyle(element)[property];
}
var cacheKey = element.id + ':' + property;
var cached = this.computedStyleCache.get(cacheKey);
if (cached && Date.now() - cached.timestamp < 1000) {
return cached.value;
}
var value = window.getComputedStyle(element)[property];
this.computedStyleCache.set(cacheKey, {
value: value,
timestamp: Date.now()
});
return value;
}
// 优化CSS选择器
function optimizeSelector(selector) {
// 移除不必要的通配符
selector = selector.replace(/\*\s+/g, '');
// 优化后代选择器
selector = selector.replace(/\s+>/g, '>');
// 移除重复的类选择器
var parts = selector.split(' ');
var uniqueParts = [...new Set(parts)];
return uniqueParts.join(' ');
}
// 检测CSS性能问题
function detectPerformanceIssues() {
var issues = [];
var stylesheets = document.styleSheets;
for (var stylesheet of stylesheets) {
try {
var rules = stylesheet.cssRules || stylesheet.rules;
for (var rule of rules) {
if (rule.type === CSSRule.STYLE_RULE) {
var selector = rule.selectorText;
// 检查复杂选择器
if (selector.split(' ').length > 4) {
issues.push({
type: 'complex-selector',
selector: selector,
message: '选择器过于复杂,可能影响性能'
});
}
// 检查通配符选择器
if (selector.includes('*')) {
issues.push({
type: 'universal-selector',
selector: selector,
message: '使用通配符选择器可能影响性能'
});
}
// 检查属性选择器
if (selector.includes('[') && !selector.includes('[id')) {
issues.push({
type: 'attribute-selector',
selector: selector,
message: '属性选择器可能影响性能'
});
}
}
}
} catch (error) {
// 跨域样式表无法访问
continue;
}
}
return issues;
}
// 清除缓存
function clearCache() {
this.styleCache.clear();
this.computedStyleCache.clear();
}
}
}
// 使用示例
function cssOptimizationExample() {
// 动画优化示例
var animationOptimizer = new CSSOptimizer.AnimationOptimizer();
var element = document.querySelector('#animated-element');
// 创建高性能动画
var animationId = animationOptimizer.createAnimation(element, {
x: 100,
y: 50,
scale: 1.2
}, {
duration: 500,
easing: 'ease-out',
onComplete: function() {
stdout.println('动画完成');
}
});
// 样式优化示例
var styleOptimizer = new CSSOptimizer.StyleOptimizer();
// 批量应用样式
styleOptimizer.applyStyles(element, {
backgroundColor: '#ff0000',
borderRadius: '10px',
padding: '20px',
margin: '10px'
});
// 检测CSS性能问题
var issues = styleOptimizer.detectPerformanceIssues();
if (issues.length > 0) {
stdout.println('发现CSS性能问题:', JSON.stringify(issues, null, 2));
}
stdout.println('CSS优化示例完成');
}
9.3 内存管理与优化
9.3.1 内存泄漏检测
// 内存管理工具
namespace MemoryManager {
// 内存泄漏检测器
class MemoryLeakDetector {
function this() {
this.references = new Map();
this.eventListeners = new Map();
this.timers = new Map();
this.observers = new Map();
this.isMonitoring = false;
}
// 开始监控
function startMonitoring() {
if (this.isMonitoring) {
return { success: false, error: '已在监控中' };
}
this.isMonitoring = true;
this.setupInterceptors();
stdout.println('内存泄漏监控已启动');
return { success: true };
}
// 停止监控
function stopMonitoring() {
if (!this.isMonitoring) {
return { success: false, error: '未在监控中' };
}
this.isMonitoring = false;
this.removeInterceptors();
var report = this.generateLeakReport();
stdout.println('内存泄漏监控已停止');
return {
success: true,
report: report
};
}
// 设置拦截器
function setupInterceptors() {
// 拦截addEventListener
var originalAddEventListener = Element.prototype.addEventListener;
var self = this;
Element.prototype.addEventListener = function(type, listener, options) {
var elementId = this.id || 'element_' + Date.now();
var listenerId = elementId + '_' + type + '_' + Date.now();
self.eventListeners.set(listenerId, {
element: this,
type: type,
listener: listener,
options: options,
timestamp: Date.now(),
stack: new Error().stack
});
return originalAddEventListener.call(this, type, listener, options);
};
// 拦截removeEventListener
var originalRemoveEventListener = Element.prototype.removeEventListener;
Element.prototype.removeEventListener = function(type, listener, options) {
// 查找并移除对应的监听器记录
for (var [id, record] of self.eventListeners) {
if (record.element === this &&
record.type === type &&
record.listener === listener) {
self.eventListeners.delete(id);
break;
}
}
return originalRemoveEventListener.call(this, type, listener, options);
};
// 拦截setTimeout
var originalSetTimeout = window.setTimeout;
window.setTimeout = function(callback, delay) {
var timerId = originalSetTimeout.call(this, callback, delay);
self.timers.set(timerId, {
type: 'timeout',
callback: callback,
delay: delay,
timestamp: Date.now(),
stack: new Error().stack
});
return timerId;
};
// 拦截setInterval
var originalSetInterval = window.setInterval;
window.setInterval = function(callback, delay) {
var timerId = originalSetInterval.call(this, callback, delay);
self.timers.set(timerId, {
type: 'interval',
callback: callback,
delay: delay,
timestamp: Date.now(),
stack: new Error().stack
});
return timerId;
};
// 拦截clearTimeout和clearInterval
var originalClearTimeout = window.clearTimeout;
var originalClearInterval = window.clearInterval;
window.clearTimeout = function(timerId) {
self.timers.delete(timerId);
return originalClearTimeout.call(this, timerId);
};
window.clearInterval = function(timerId) {
self.timers.delete(timerId);
return originalClearInterval.call(this, timerId);
};
}
// 移除拦截器
function removeInterceptors() {
// 这里应该恢复原始方法,但为了简化示例,我们跳过这一步
// 在实际应用中,应该保存原始方法的引用并在这里恢复
}
// 注册对象引用
function registerReference(object, name, context = '') {
var refId = name + '_' + Date.now();
this.references.set(refId, {
object: object,
name: name,
context: context,
timestamp: Date.now(),
stack: new Error().stack
});
return refId;
}
// 注销对象引用
function unregisterReference(refId) {
return this.references.delete(refId);
}
// 检查悬空引用
function checkDanglingReferences() {
var danglingRefs = [];
for (var [id, ref] of this.references) {
try {
// 尝试访问对象属性来检查对象是否仍然有效
if (ref.object && typeof ref.object === 'object') {
// 检查DOM元素是否仍在文档中
if (ref.object.nodeType && !document.contains(ref.object)) {
danglingRefs.push({
id: id,
name: ref.name,
context: ref.context,
type: 'detached-dom',
age: Date.now() - ref.timestamp
});
}
}
} catch (error) {
danglingRefs.push({
id: id,
name: ref.name,
context: ref.context,
type: 'invalid-reference',
age: Date.now() - ref.timestamp,
error: error.message
});
}
}
return danglingRefs;
}
// 检查未清理的事件监听器
function checkUncleanedListeners() {
var uncleanedListeners = [];
for (var [id, listener] of this.eventListeners) {
try {
// 检查元素是否仍在文档中
if (!document.contains(listener.element)) {
uncleanedListeners.push({
id: id,
type: listener.type,
elementId: listener.element.id || 'unknown',
age: Date.now() - listener.timestamp
});
}
} catch (error) {
uncleanedListeners.push({
id: id,
type: listener.type,
age: Date.now() - listener.timestamp,
error: error.message
});
}
}
return uncleanedListeners;
}
// 检查未清理的定时器
function checkUncleanedTimers() {
var uncleanedTimers = [];
var currentTime = Date.now();
for (var [id, timer] of this.timers) {
var age = currentTime - timer.timestamp;
// 如果定时器存在时间过长,可能是泄漏
if (age > 60000) { // 1分钟
uncleanedTimers.push({
id: id,
type: timer.type,
delay: timer.delay,
age: age
});
}
}
return uncleanedTimers;
}
// 生成泄漏报告
function generateLeakReport() {
var danglingRefs = this.checkDanglingReferences();
var uncleanedListeners = this.checkUncleanedListeners();
var uncleanedTimers = this.checkUncleanedTimers();
return {
timestamp: new Date().toISOString(),
summary: {
totalReferences: this.references.size,
totalListeners: this.eventListeners.size,
totalTimers: this.timers.size,
danglingReferences: danglingRefs.length,
uncleanedListeners: uncleanedListeners.length,
uncleanedTimers: uncleanedTimers.length
},
details: {
danglingReferences: danglingRefs,
uncleanedListeners: uncleanedListeners,
uncleanedTimers: uncleanedTimers
},
recommendations: this.generateRecommendations(danglingRefs, uncleanedListeners, uncleanedTimers)
};
}
// 生成优化建议
function generateRecommendations(danglingRefs, uncleanedListeners, uncleanedTimers) {
var recommendations = [];
if (danglingRefs.length > 0) {
recommendations.push('清理悬空对象引用,特别是已从DOM中移除的元素');
}
if (uncleanedListeners.length > 0) {
recommendations.push('在移除DOM元素前,确保移除所有事件监听器');
}
if (uncleanedTimers.length > 0) {
recommendations.push('清理长时间运行的定时器,使用clearTimeout/clearInterval');
}
if (recommendations.length === 0) {
recommendations.push('未发现明显的内存泄漏问题');
}
return recommendations;
}
// 强制垃圾回收(如果支持)
function forceGarbageCollection() {
try {
if (window.gc) {
window.gc();
return { success: true, message: '垃圾回收已执行' };
} else {
return { success: false, message: '垃圾回收不可用' };
}
} catch (error) {
return { success: false, error: error.message };
}
}
}
// 对象池管理
class ObjectPool {
function this(createFn, resetFn, maxSize = 100) {
this.createFn = createFn;
this.resetFn = resetFn;
this.maxSize = maxSize;
this.pool = [];
this.activeObjects = new Set();
}
// 获取对象
function acquire() {
var obj;
if (this.pool.length > 0) {
obj = this.pool.pop();
} else {
obj = this.createFn();
}
this.activeObjects.add(obj);
return obj;
}
// 释放对象
function release(obj) {
if (!this.activeObjects.has(obj)) {
return false;
}
this.activeObjects.delete(obj);
if (this.pool.length < this.maxSize) {
if (this.resetFn) {
this.resetFn(obj);
}
this.pool.push(obj);
}
return true;
}
// 清空池
function clear() {
this.pool = [];
this.activeObjects.clear();
}
// 获取统计信息
function getStats() {
return {
poolSize: this.pool.length,
activeCount: this.activeObjects.size,
maxSize: this.maxSize
};
}
}
// 弱引用管理器
class WeakReferenceManager {
function this() {
this.weakRefs = new Map();
this.cleanupInterval = null;
}
// 创建弱引用
function createWeakRef(object, callback = null) {
var refId = 'weak_' + Date.now() + '_' + Math.random();
// 模拟弱引用(Sciter可能不支持WeakRef)
var weakRef = {
id: refId,
target: object,
callback: callback,
timestamp: Date.now()
};
this.weakRefs.set(refId, weakRef);
// 启动清理定时器
if (!this.cleanupInterval) {
this.startCleanup();
}
return refId;
}
// 获取弱引用对象
function getWeakRef(refId) {
var weakRef = this.weakRefs.get(refId);
return weakRef ? weakRef.target : null;
}
// 删除弱引用
function deleteWeakRef(refId) {
var weakRef = this.weakRefs.get(refId);
if (weakRef && weakRef.callback) {
weakRef.callback();
}
return this.weakRefs.delete(refId);
}
// 启动清理
function startCleanup() {
this.cleanupInterval = setInterval(() => {
this.cleanup();
}, 30000); // 30秒清理一次
}
// 清理无效引用
function cleanup() {
var toDelete = [];
for (var [id, weakRef] of this.weakRefs) {
try {
// 检查对象是否仍然有效
if (!weakRef.target ||
(weakRef.target.nodeType && !document.contains(weakRef.target))) {
toDelete.push(id);
}
} catch (error) {
toDelete.push(id);
}
}
for (var id of toDelete) {
this.deleteWeakRef(id);
}
if (this.weakRefs.size === 0 && this.cleanupInterval) {
clearInterval(this.cleanupInterval);
this.cleanupInterval = null;
}
}
// 获取统计信息
function getStats() {
return {
weakRefCount: this.weakRefs.size,
isCleanupActive: this.cleanupInterval !== null
};
}
}
}
// 使用示例
function memoryManagementExample() {
// 内存泄漏检测示例
var leakDetector = new MemoryManager.MemoryLeakDetector();
leakDetector.startMonitoring();
// 模拟一些可能导致内存泄漏的操作
var element = document.createElement('div');
element.addEventListener('click', function() {
console.log('clicked');
});
// 注册引用
var refId = leakDetector.registerReference(element, 'test-element', 'example');
// 模拟移除元素但忘记清理事件监听器
document.body.appendChild(element);
document.body.removeChild(element);
// 检查泄漏
setTimeout(() => {
var report = leakDetector.stopMonitoring();
stdout.println('内存泄漏报告:', JSON.stringify(report.report, null, 2));
}, 2000);
// 对象池示例
var elementPool = new MemoryManager.ObjectPool(
function() {
return document.createElement('div');
},
function(element) {
element.innerHTML = '';
element.className = '';
element.style.cssText = '';
},
50
);
// 使用对象池
var pooledElement = elementPool.acquire();
pooledElement.textContent = '池化元素';
// 使用完毕后释放
elementPool.release(pooledElement);
stdout.println('对象池统计:', JSON.stringify(elementPool.getStats(), null, 2));
// 弱引用管理示例
var weakRefManager = new MemoryManager.WeakReferenceManager();
var testObject = { name: 'test' };
var weakRefId = weakRefManager.createWeakRef(testObject, function() {
stdout.println('弱引用对象被清理');
});
stdout.println('弱引用管理器统计:', JSON.stringify(weakRefManager.getStats(), null, 2));
}
9.4 脚本性能优化
9.4.1 代码执行优化
// 脚本性能优化工具
namespace ScriptOptimizer {
// 函数执行时间分析器
class FunctionProfiler {
function this() {
this.profiles = new Map();
this.isEnabled = false;
this.callStack = [];
}
// 启用分析
function enable() {
this.isEnabled = true;
stdout.println('函数性能分析已启用');
}
// 禁用分析
function disable() {
this.isEnabled = false;
stdout.println('函数性能分析已禁用');
}
// 包装函数进行分析
function wrapFunction(fn, name) {
var self = this;
return function() {
if (!self.isEnabled) {
return fn.apply(this, arguments);
}
var startTime = performance.now();
var startMemory = System.memory.getUsage().used;
self.callStack.push({
name: name,
startTime: startTime,
startMemory: startMemory
});
try {
var result = fn.apply(this, arguments);
var endTime = performance.now();
var endMemory = System.memory.getUsage().used;
var duration = endTime - startTime;
var memoryDelta = endMemory - startMemory;
self.recordProfile(name, duration, memoryDelta, true);
return result;
} catch (error) {
var endTime = performance.now();
var duration = endTime - startTime;
self.recordProfile(name, duration, 0, false, error);
throw error;
} finally {
self.callStack.pop();
}
};
}
// 记录性能数据
function recordProfile(name, duration, memoryDelta, success, error = null) {
if (!this.profiles.has(name)) {
this.profiles.set(name, {
name: name,
callCount: 0,
totalTime: 0,
minTime: Infinity,
maxTime: 0,
avgTime: 0,
totalMemory: 0,
errors: 0,
lastError: null
});
}
var profile = this.profiles.get(name);
profile.callCount++;
profile.totalTime += duration;
profile.minTime = Math.min(profile.minTime, duration);
profile.maxTime = Math.max(profile.maxTime, duration);
profile.avgTime = profile.totalTime / profile.callCount;
profile.totalMemory += memoryDelta;
if (!success) {
profile.errors++;
profile.lastError = error ? error.message : 'Unknown error';
}
}
// 获取性能报告
function getReport() {
var profiles = [];
for (var [name, profile] of this.profiles) {
profiles.push({
name: profile.name,
callCount: profile.callCount,
totalTime: profile.totalTime.toFixed(2),
avgTime: profile.avgTime.toFixed(2),
minTime: profile.minTime.toFixed(2),
maxTime: profile.maxTime.toFixed(2),
totalMemory: profile.totalMemory,
errorRate: (profile.errors / profile.callCount * 100).toFixed(2) + '%',
lastError: profile.lastError
});
}
// 按平均执行时间排序
profiles.sort((a, b) => parseFloat(b.avgTime) - parseFloat(a.avgTime));
return {
timestamp: new Date().toISOString(),
totalFunctions: profiles.length,
profiles: profiles,
recommendations: this.generateRecommendations(profiles)
};
}
// 生成优化建议
function generateRecommendations(profiles) {
var recommendations = [];
for (var profile of profiles) {
if (parseFloat(profile.avgTime) > 10) {
recommendations.push(`函数 ${profile.name} 平均执行时间过长 (${profile.avgTime}ms),建议优化`);
}
if (parseFloat(profile.errorRate) > 5) {
recommendations.push(`函数 ${profile.name} 错误率过高 (${profile.errorRate}),建议检查错误处理`);
}
if (profile.totalMemory > 1024 * 1024) {
recommendations.push(`函数 ${profile.name} 内存使用过多,建议检查内存泄漏`);
}
}
return recommendations;
}
// 清除分析数据
function clear() {
this.profiles.clear();
this.callStack = [];
}
// 获取当前调用栈
function getCurrentCallStack() {
return this.callStack.map(call => call.name);
}
}
// 代码热点分析器
class HotspotAnalyzer {
function this() {
this.hotspots = new Map();
this.samplingInterval = 10; // 10ms采样间隔
this.isRunning = false;
this.samplingTimer = null;
}
// 开始分析
function startAnalysis() {
if (this.isRunning) {
return { success: false, error: '分析已在运行' };
}
this.isRunning = true;
this.startSampling();
stdout.println('热点分析已启动');
return { success: true };
}
// 停止分析
function stopAnalysis() {
if (!this.isRunning) {
return { success: false, error: '分析未运行' };
}
this.isRunning = false;
this.stopSampling();
var report = this.generateHotspotReport();
stdout.println('热点分析已停止');
return {
success: true,
report: report
};
}
// 开始采样
function startSampling() {
this.samplingTimer = setInterval(() => {
this.sampleCurrentExecution();
}, this.samplingInterval);
}
// 停止采样
function stopSampling() {
if (this.samplingTimer) {
clearInterval(this.samplingTimer);
this.samplingTimer = null;
}
}
// 采样当前执行
function sampleCurrentExecution() {
try {
// 获取当前调用栈(简化实现)
var stack = new Error().stack;
var lines = stack.split('\n');
for (var line of lines) {
if (line.includes('at ')) {
var functionName = this.extractFunctionName(line);
if (functionName) {
this.recordHotspot(functionName);
}
}
}
} catch (error) {
// 忽略采样错误
}
}
// 提取函数名
function extractFunctionName(stackLine) {
var match = stackLine.match(/at\s+([^\s]+)/);
return match ? match[1] : null;
}
// 记录热点
function recordHotspot(functionName) {
if (!this.hotspots.has(functionName)) {
this.hotspots.set(functionName, {
name: functionName,
sampleCount: 0,
percentage: 0
});
}
var hotspot = this.hotspots.get(functionName);
hotspot.sampleCount++;
}
// 生成热点报告
function generateHotspotReport() {
var totalSamples = 0;
for (var [name, hotspot] of this.hotspots) {
totalSamples += hotspot.sampleCount;
}
var hotspots = [];
for (var [name, hotspot] of this.hotspots) {
hotspot.percentage = (hotspot.sampleCount / totalSamples * 100).toFixed(2);
hotspots.push(hotspot);
}
// 按采样次数排序
hotspots.sort((a, b) => b.sampleCount - a.sampleCount);
return {
timestamp: new Date().toISOString(),
totalSamples: totalSamples,
samplingInterval: this.samplingInterval,
hotspots: hotspots.slice(0, 20), // 只返回前20个热点
recommendations: this.generateHotspotRecommendations(hotspots)
};
}
// 生成热点优化建议
function generateHotspotRecommendations(hotspots) {
var recommendations = [];
for (var i = 0; i < Math.min(5, hotspots.length); i++) {
var hotspot = hotspots[i];
if (parseFloat(hotspot.percentage) > 10) {
recommendations.push(`函数 ${hotspot.name} 占用 ${hotspot.percentage}% 的执行时间,建议优化`);
}
}
return recommendations;
}
// 清除数据
function clear() {
this.hotspots.clear();
}
}
// 异步操作优化器
class AsyncOptimizer {
function this() {
this.pendingOperations = new Map();
this.completedOperations = [];
this.maxConcurrency = 5;
this.currentConcurrency = 0;
}
// 批量执行异步操作
function batchExecute(operations, options = {}) {
var {
concurrency = this.maxConcurrency,
timeout = 30000,
retries = 3
} = options;
return new Promise((resolve, reject) => {
var results = [];
var completed = 0;
var failed = 0;
var executeNext = () => {
if (this.currentConcurrency >= concurrency || operations.length === 0) {
return;
}
var operation = operations.shift();
if (!operation) {
return;
}
this.currentConcurrency++;
var startTime = Date.now();
var executeOperation = (retryCount = 0) => {
operation()
.then(result => {
results.push({
success: true,
result: result,
duration: Date.now() - startTime
});
completed++;
this.currentConcurrency--;
if (completed + failed === results.length) {
resolve({
success: true,
results: results,
completed: completed,
failed: failed
});
} else {
executeNext();
}
})
.catch(error => {
if (retryCount < retries) {
setTimeout(() => {
executeOperation(retryCount + 1);
}, 1000 * Math.pow(2, retryCount)); // 指数退避
} else {
results.push({
success: false,
error: error.message,
duration: Date.now() - startTime
});
failed++;
this.currentConcurrency--;
if (completed + failed === results.length) {
resolve({
success: false,
results: results,
completed: completed,
failed: failed
});
} else {
executeNext();
}
}
});
};
executeOperation();
executeNext();
};
// 启动初始并发操作
for (var i = 0; i < Math.min(concurrency, operations.length); i++) {
executeNext();
}
// 设置超时
setTimeout(() => {
reject(new Error('批量操作超时'));
}, timeout);
});
}
// 防抖函数
function debounce(func, delay) {
var timeoutId;
return function() {
var context = this;
var args = arguments;
clearTimeout(timeoutId);
timeoutId = setTimeout(function() {
func.apply(context, args);
}, delay);
};
}
// 节流函数
function throttle(func, limit) {
var inThrottle;
return function() {
var context = this;
var args = arguments;
if (!inThrottle) {
func.apply(context, args);
inThrottle = true;
setTimeout(function() {
inThrottle = false;
}, limit);
}
};
}
// 缓存函数结果
function memoize(func, keyGenerator = null) {
var cache = new Map();
return function() {
var key = keyGenerator ?
keyGenerator.apply(this, arguments) :
JSON.stringify(arguments);
if (cache.has(key)) {
return cache.get(key);
}
var result = func.apply(this, arguments);
cache.set(key, result);
return result;
};
}
// 获取统计信息
function getStats() {
return {
pendingOperations: this.pendingOperations.size,
completedOperations: this.completedOperations.length,
currentConcurrency: this.currentConcurrency,
maxConcurrency: this.maxConcurrency
};
}
}
}
// 使用示例
function scriptOptimizationExample() {
// 函数性能分析示例
var profiler = new ScriptOptimizer.FunctionProfiler();
profiler.enable();
// 包装函数进行分析
function slowFunction() {
var start = Date.now();
while (Date.now() - start < 50) {
// 模拟耗时操作
}
return 'completed';
}
var wrappedFunction = profiler.wrapFunction(slowFunction, 'slowFunction');
// 多次调用函数
for (var i = 0; i < 10; i++) {
wrappedFunction();
}
// 获取性能报告
var report = profiler.getReport();
stdout.println('函数性能报告:', JSON.stringify(report, null, 2));
// 热点分析示例
var hotspotAnalyzer = new ScriptOptimizer.HotspotAnalyzer();
hotspotAnalyzer.startAnalysis();
// 模拟一些计算密集的操作
setTimeout(() => {
for (var i = 0; i < 1000; i++) {
Math.sqrt(i);
}
var hotspotReport = hotspotAnalyzer.stopAnalysis();
stdout.println('热点分析报告:', JSON.stringify(hotspotReport.report, null, 2));
}, 1000);
// 异步优化示例
var asyncOptimizer = new ScriptOptimizer.AsyncOptimizer();
// 创建一些异步操作
var operations = [];
for (var i = 0; i < 10; i++) {
operations.push(() => {
return new Promise(resolve => {
setTimeout(() => {
resolve(`操作 ${i} 完成`);
}, Math.random() * 1000);
});
});
}
// 批量执行
asyncOptimizer.batchExecute(operations, {
concurrency: 3,
timeout: 5000,
retries: 2
}).then(result => {
stdout.println('批量异步操作结果:', JSON.stringify(result, null, 2));
});
// 防抖和节流示例
var debouncedFunction = asyncOptimizer.debounce(function() {
stdout.println('防抖函数执行');
}, 300);
var throttledFunction = asyncOptimizer.throttle(function() {
stdout.println('节流函数执行');
}, 1000);
// 缓存示例
var expensiveFunction = function(n) {
var result = 0;
for (var i = 0; i < n; i++) {
result += Math.sqrt(i);
}
return result;
};
var memoizedFunction = asyncOptimizer.memoize(expensiveFunction);
stdout.println('脚本优化示例完成');
}
9.5 调试工具与技巧
9.5.1 调试器集成
// 调试工具集合
namespace DebugTools {
// 调试器
class Debugger {
function this() {
this.breakpoints = new Map();
this.watchExpressions = new Map();
this.callStack = [];
this.variables = new Map();
this.isEnabled = false;
this.stepMode = false;
this.stepCallback = null;
}
// 启用调试器
function enable() {
this.isEnabled = true;
this.setupGlobalErrorHandler();
stdout.println('调试器已启用');
}
// 禁用调试器
function disable() {
this.isEnabled = false;
stdout.println('调试器已禁用');
}
// 设置断点
function setBreakpoint(file, line, condition = null) {
var id = `${file}:${line}`;
this.breakpoints.set(id, {
file: file,
line: line,
condition: condition,
enabled: true,
hitCount: 0
});
stdout.println(`断点已设置: ${id}`);
return id;
}
// 移除断点
function removeBreakpoint(id) {
var removed = this.breakpoints.delete(id);
if (removed) {
stdout.println(`断点已移除: ${id}`);
}
return removed;
}
// 添加监视表达式
function addWatch(expression, name = null) {
var watchId = name || `watch_${Date.now()}`;
this.watchExpressions.set(watchId, {
expression: expression,
name: name || expression,
lastValue: null,
changed: false
});
stdout.println(`监视表达式已添加: ${watchId}`);
return watchId;
}
// 移除监视表达式
function removeWatch(watchId) {
var removed = this.watchExpressions.delete(watchId);
if (removed) {
stdout.println(`监视表达式已移除: ${watchId}`);
}
return removed;
}
// 检查断点
function checkBreakpoint(file, line, context = {}) {
if (!this.isEnabled) {
return false;
}
var id = `${file}:${line}`;
var breakpoint = this.breakpoints.get(id);
if (!breakpoint || !breakpoint.enabled) {
return false;
}
breakpoint.hitCount++;
// 检查条件
if (breakpoint.condition) {
try {
var conditionResult = this.evaluateExpression(breakpoint.condition, context);
if (!conditionResult) {
return false;
}
} catch (error) {
stdout.println(`断点条件错误: ${error.message}`);
return false;
}
}
this.onBreakpointHit(breakpoint, context);
return true;
}
// 断点命中处理
function onBreakpointHit(breakpoint, context) {
stdout.println(`断点命中: ${breakpoint.file}:${breakpoint.line}`);
// 更新调用栈
this.updateCallStack();
// 更新变量
this.updateVariables(context);
// 评估监视表达式
this.evaluateWatchExpressions(context);
// 进入步进模式
this.enterStepMode();
}
// 更新调用栈
function updateCallStack() {
try {
var stack = new Error().stack;
var lines = stack.split('\n');
this.callStack = lines.map((line, index) => {
return {
level: index,
function: this.extractFunctionName(line),
location: this.extractLocation(line)
};
}).filter(frame => frame.function);
} catch (error) {
this.callStack = [];
}
}
// 更新变量
function updateVariables(context) {
this.variables.clear();
for (var key in context) {
if (context.hasOwnProperty(key)) {
this.variables.set(key, {
name: key,
value: context[key],
type: typeof context[key]
});
}
}
}
// 评估监视表达式
function evaluateWatchExpressions(context) {
for (var [id, watch] of this.watchExpressions) {
try {
var newValue = this.evaluateExpression(watch.expression, context);
watch.changed = watch.lastValue !== newValue;
watch.lastValue = newValue;
if (watch.changed) {
stdout.println(`监视表达式变化: ${watch.name} = ${newValue}`);
}
} catch (error) {
watch.lastValue = `错误: ${error.message}`;
watch.changed = true;
}
}
}
// 评估表达式
function evaluateExpression(expression, context) {
// 简化的表达式评估(实际实现会更复杂)
try {
// 创建一个安全的评估环境
var func = new Function('context', `
with (context) {
return ${expression};
}
`);
return func(context);
} catch (error) {
throw new Error(`表达式评估失败: ${error.message}`);
}
}
// 进入步进模式
function enterStepMode() {
this.stepMode = true;
stdout.println('进入步进模式,使用 step(), stepOver(), stepOut(), continue() 控制执行');
}
// 单步执行
function step() {
if (this.stepCallback) {
this.stepCallback('step');
}
stdout.println('单步执行');
}
// 步过
function stepOver() {
if (this.stepCallback) {
this.stepCallback('stepOver');
}
stdout.println('步过执行');
}
// 步出
function stepOut() {
if (this.stepCallback) {
this.stepCallback('stepOut');
}
stdout.println('步出执行');
}
// 继续执行
function continue() {
this.stepMode = false;
if (this.stepCallback) {
this.stepCallback('continue');
}
stdout.println('继续执行');
}
// 设置步进回调
function setStepCallback(callback) {
this.stepCallback = callback;
}
// 获取调试信息
function getDebugInfo() {
return {
breakpoints: Array.from(this.breakpoints.values()),
watchExpressions: Array.from(this.watchExpressions.values()),
callStack: this.callStack,
variables: Array.from(this.variables.values()),
isEnabled: this.isEnabled,
stepMode: this.stepMode
};
}
// 设置全局错误处理器
function setupGlobalErrorHandler() {
var self = this;
window.addEventListener('error', function(event) {
if (self.isEnabled) {
stdout.println(`全局错误: ${event.error.message}`);
stdout.println(`位置: ${event.filename}:${event.lineno}:${event.colno}`);
// 自动设置断点到错误位置
if (event.filename && event.lineno) {
self.setBreakpoint(event.filename, event.lineno);
}
}
});
}
// 提取函数名
function extractFunctionName(stackLine) {
var match = stackLine.match(/at\s+([^\s]+)/);
return match ? match[1] : 'anonymous';
}
// 提取位置信息
function extractLocation(stackLine) {
var match = stackLine.match(/\(([^)]+)\)$/);
return match ? match[1] : 'unknown';
}
}
// 日志管理器
class Logger {
function this() {
this.logs = [];
this.maxLogs = 1000;
this.logLevel = 'info';
this.filters = [];
this.outputs = ['console'];
}
// 设置日志级别
function setLevel(level) {
this.logLevel = level;
}
// 添加过滤器
function addFilter(filter) {
this.filters.push(filter);
}
// 添加输出目标
function addOutput(output) {
if (this.outputs.indexOf(output) === -1) {
this.outputs.push(output);
}
}
// 记录日志
function log(level, message, data = null) {
var logEntry = {
timestamp: new Date().toISOString(),
level: level,
message: message,
data: data,
stack: new Error().stack
};
// 应用过滤器
for (var filter of this.filters) {
if (!filter(logEntry)) {
return;
}
}
// 检查日志级别
if (!this.shouldLog(level)) {
return;
}
// 添加到日志列表
this.logs.push(logEntry);
// 限制日志数量
if (this.logs.length > this.maxLogs) {
this.logs.shift();
}
// 输出日志
this.outputLog(logEntry);
}
// 检查是否应该记录日志
function shouldLog(level) {
var levels = ['debug', 'info', 'warn', 'error'];
var currentLevelIndex = levels.indexOf(this.logLevel);
var logLevelIndex = levels.indexOf(level);
return logLevelIndex >= currentLevelIndex;
}
// 输出日志
function outputLog(logEntry) {
var formattedMessage = `[${logEntry.timestamp}] [${logEntry.level.toUpperCase()}] ${logEntry.message}`;
for (var output of this.outputs) {
switch (output) {
case 'console':
stdout.println(formattedMessage);
if (logEntry.data) {
stdout.println('数据:', JSON.stringify(logEntry.data, null, 2));
}
break;
case 'file':
// 文件输出实现
this.writeToFile(formattedMessage, logEntry.data);
break;
}
}
}
// 写入文件
function writeToFile(message, data) {
try {
var logFile = 'debug.log';
var content = message;
if (data) {
content += '\n' + JSON.stringify(data, null, 2);
}
content += '\n';
// 这里应该使用实际的文件写入API
// System.fs.appendFile(logFile, content);
} catch (error) {
stdout.println('写入日志文件失败:', error.message);
}
}
// 便捷方法
function debug(message, data) {
this.log('debug', message, data);
}
function info(message, data) {
this.log('info', message, data);
}
function warn(message, data) {
this.log('warn', message, data);
}
function error(message, data) {
this.log('error', message, data);
}
// 获取日志
function getLogs(filter = null) {
if (filter) {
return this.logs.filter(filter);
}
return this.logs.slice();
}
// 清除日志
function clear() {
this.logs = [];
}
// 导出日志
function exportLogs(format = 'json') {
switch (format) {
case 'json':
return JSON.stringify(this.logs, null, 2);
case 'csv':
return this.exportToCSV();
case 'text':
return this.exportToText();
default:
return JSON.stringify(this.logs, null, 2);
}
}
// 导出为CSV
function exportToCSV() {
var csv = 'Timestamp,Level,Message,Data\n';
for (var log of this.logs) {
var data = log.data ? JSON.stringify(log.data).replace(/"/g, '""') : '';
csv += `"${log.timestamp}","${log.level}","${log.message}","${data}"\n`;
}
return csv;
}
// 导出为文本
function exportToText() {
var text = '';
for (var log of this.logs) {
text += `[${log.timestamp}] [${log.level.toUpperCase()}] ${log.message}\n`;
if (log.data) {
text += JSON.stringify(log.data, null, 2) + '\n';
}
text += '\n';
}
return text;
}
}
// 性能分析器
class Profiler {
function this() {
this.profiles = new Map();
this.activeProfiles = new Map();
this.isEnabled = false;
}
// 启用分析器
function enable() {
this.isEnabled = true;
stdout.println('性能分析器已启用');
}
// 禁用分析器
function disable() {
this.isEnabled = false;
stdout.println('性能分析器已禁用');
}
// 开始分析
function start(name) {
if (!this.isEnabled) {
return;
}
this.activeProfiles.set(name, {
name: name,
startTime: performance.now(),
startMemory: this.getMemoryUsage()
});
}
// 结束分析
function end(name) {
if (!this.isEnabled || !this.activeProfiles.has(name)) {
return null;
}
var profile = this.activeProfiles.get(name);
var endTime = performance.now();
var endMemory = this.getMemoryUsage();
var result = {
name: name,
duration: endTime - profile.startTime,
memoryDelta: endMemory - profile.startMemory,
timestamp: new Date().toISOString()
};
// 保存到历史记录
if (!this.profiles.has(name)) {
this.profiles.set(name, []);
}
this.profiles.get(name).push(result);
this.activeProfiles.delete(name);
return result;
}
// 获取内存使用情况
function getMemoryUsage() {
try {
if (System && System.memory) {
return System.memory.getUsage().used;
}
return 0;
} catch (error) {
return 0;
}
}
// 获取分析报告
function getReport(name = null) {
if (name) {
var profiles = this.profiles.get(name) || [];
return this.generateReport(name, profiles);
}
var reports = {};
for (var [profileName, profiles] of this.profiles) {
reports[profileName] = this.generateReport(profileName, profiles);
}
return reports;
}
// 生成报告
function generateReport(name, profiles) {
if (profiles.length === 0) {
return {
name: name,
count: 0,
avgDuration: 0,
minDuration: 0,
maxDuration: 0,
totalDuration: 0,
avgMemory: 0,
totalMemory: 0
};
}
var totalDuration = profiles.reduce((sum, p) => sum + p.duration, 0);
var totalMemory = profiles.reduce((sum, p) => sum + p.memoryDelta, 0);
var durations = profiles.map(p => p.duration);
return {
name: name,
count: profiles.length,
avgDuration: totalDuration / profiles.length,
minDuration: Math.min(...durations),
maxDuration: Math.max(...durations),
totalDuration: totalDuration,
avgMemory: totalMemory / profiles.length,
totalMemory: totalMemory
};
}
// 清除分析数据
function clear(name = null) {
if (name) {
this.profiles.delete(name);
} else {
this.profiles.clear();
}
}
}
}
// 使用示例
function debugToolsExample() {
// 调试器示例
var debugger = new DebugTools.Debugger();
debugger.enable();
// 设置断点
debugger.setBreakpoint('example.js', 10, 'x > 5');
// 添加监视表达式
debugger.addWatch('x * 2', 'doubleX');
// 模拟断点检查
var context = { x: 6, y: 10 };
debugger.checkBreakpoint('example.js', 10, context);
// 日志管理器示例
var logger = new DebugTools.Logger();
logger.setLevel('debug');
logger.addOutput('file');
logger.debug('调试信息', { userId: 123 });
logger.info('应用启动');
logger.warn('性能警告', { duration: 1500 });
logger.error('发生错误', { error: 'Network timeout' });
// 性能分析器示例
var profiler = new DebugTools.Profiler();
profiler.enable();
// 分析函数执行
profiler.start('dataProcessing');
// 模拟数据处理
for (var i = 0; i < 1000; i++) {
Math.sqrt(i);
}
var result = profiler.end('dataProcessing');
stdout.println('性能分析结果:', JSON.stringify(result, null, 2));
// 获取完整报告
var report = profiler.getReport();
stdout.println('性能报告:', JSON.stringify(report, null, 2));
stdout.println('调试工具示例完成');
}
9.6 本章总结
9.6.1 核心要点
性能监控
- 实时性能指标收集
- 性能瓶颈识别
- 自动化性能报告
- 性能警告机制
DOM性能优化
- 批量DOM操作
- 虚拟滚动技术
- DOM查询优化
- 减少重排重绘
CSS性能优化
- 高性能动画
- 样式批量应用
- CSS选择器优化
- 样式缓存机制
内存管理
- 内存泄漏检测
- 对象池管理
- 弱引用机制
- 垃圾回收优化
脚本性能优化
- 函数性能分析
- 代码热点检测
- 异步操作优化
- 缓存和防抖节流
调试工具
- 断点调试
- 日志管理
- 性能分析
- 错误追踪
9.6.2 最佳实践
性能优化策略
- 先测量,后优化
- 关注关键路径
- 渐进式优化
- 持续监控
内存管理原则
- 及时清理资源
- 避免循环引用
- 使用对象池
- 监控内存使用
调试技巧
- 结构化日志
- 条件断点
- 性能分析
- 错误处理
代码优化
- 减少DOM操作
- 优化算法复杂度
- 使用缓存
- 异步处理
9.6.3 练习题
基础练习
性能监控器
- 实现一个简单的性能监控器
- 监控页面加载时间
- 记录用户交互响应时间
内存泄漏检测
- 创建一个内存泄漏检测工具
- 检测未清理的事件监听器
- 检测悬空DOM引用
日志系统
- 实现一个日志管理系统
- 支持不同日志级别
- 支持日志过滤和导出
进阶练习
虚拟滚动组件
- 实现一个高性能的虚拟滚动列表
- 支持动态高度
- 支持水平和垂直滚动
性能分析器
- 创建一个函数性能分析器
- 支持调用栈分析
- 生成性能报告
调试面板
- 实现一个可视化调试面板
- 显示性能指标
- 支持实时监控
高级练习
完整的性能优化方案
- 为一个复杂应用设计性能优化方案
- 包含监控、分析、优化的完整流程
- 实现自动化性能测试
内存管理框架
- 设计一个完整的内存管理框架
- 支持自动垃圾回收
- 提供内存使用分析
调试工具集
- 开发一套完整的调试工具
- 包含断点、监视、分析等功能
- 支持远程调试
通过本章的学习,你应该掌握了Sciter应用的性能优化和调试技巧。下一章我们将学习项目实战与部署,将所学知识应用到实际项目中。