第八章:性能优化与最佳实践
在前面的章节中,我们构建了一个功能完整的插件系统。现在我们要关注性能优化和开发最佳实践,确保插件系统在实际应用中能够高效、稳定地运行。
性能优化策略
1. 插件加载优化
懒加载机制
javascript
// lazy-plugin-loader.js
class LazyPluginLoader {
constructor(pluginManager) {
this.pluginManager = pluginManager;
this.lazyPlugins = new Map();
this.loadPromises = new Map();
}
// 注册懒加载插件
registerLazy(name, loader, conditions = {}) {
this.lazyPlugins.set(name, {
loader,
conditions,
loaded: false,
instance: null
});
}
// 检查是否需要加载插件
async checkAndLoad(name, context = {}) {
const lazyPlugin = this.lazyPlugins.get(name);
if (!lazyPlugin || lazyPlugin.loaded) {
return lazyPlugin?.instance;
}
// 检查加载条件
if (!this.shouldLoad(lazyPlugin.conditions, context)) {
return null;
}
// 防止重复加载
if (this.loadPromises.has(name)) {
return await this.loadPromises.get(name);
}
// 开始加载
const loadPromise = this.loadPlugin(name, lazyPlugin);
this.loadPromises.set(name, loadPromise);
try {
const instance = await loadPromise;
lazyPlugin.loaded = true;
lazyPlugin.instance = instance;
this.loadPromises.delete(name);
return instance;
} catch (error) {
this.loadPromises.delete(name);
throw error;
}
}
// 加载插件
async loadPlugin(name, lazyPlugin) {
console.log(`🔄 Lazy loading plugin: ${name}`);
const startTime = Date.now();
try {
// 执行加载器
const PluginClass = await lazyPlugin.loader();
const instance = new PluginClass();
// 注册到插件管理器
await this.pluginManager.register(instance);
await this.pluginManager.initPlugin(instance.name);
await this.pluginManager.enablePlugin(instance.name);
const loadTime = Date.now() - startTime;
console.log(`✅ Plugin ${name} loaded in ${loadTime}ms`);
return instance;
} catch (error) {
console.error(`❌ Failed to load plugin ${name}:`, error);
throw error;
}
}
// 检查是否应该加载
shouldLoad(conditions, context) {
if (!conditions || Object.keys(conditions).length === 0) {
return true;
}
// 检查触发条件
if (conditions.trigger && !context[conditions.trigger]) {
return false;
}
// 检查环境条件
if (conditions.env && process.env.NODE_ENV !== conditions.env) {
return false;
}
// 检查特性标志
if (conditions.feature && !context.features?.[conditions.feature]) {
return false;
}
return true;
}
// 预加载插件
async preload(names, context = {}) {
const promises = names.map(name => this.checkAndLoad(name, context));
return await Promise.allSettled(promises);
}
// 获取加载状态
getLoadStatus() {
const status = {};
for (const [name, plugin] of this.lazyPlugins) {
status[name] = {
loaded: plugin.loaded,
loading: this.loadPromises.has(name)
};
}
return status;
}
}
module.exports = LazyPluginLoader;
插件缓存系统
javascript
// plugin-cache.js
class PluginCache {
constructor(options = {}) {
this.cache = new Map();
this.metadata = new Map();
this.maxSize = options.maxSize || 100;
this.ttl = options.ttl || 3600000; // 1小时
this.hitCount = 0;
this.missCount = 0;
}
// 缓存插件实例
set(key, plugin, metadata = {}) {
// 检查缓存大小
if (this.cache.size >= this.maxSize) {
this.evictLRU();
}
const cacheEntry = {
plugin,
timestamp: Date.now(),
accessCount: 0,
lastAccess: Date.now()
};
this.cache.set(key, cacheEntry);
this.metadata.set(key, metadata);
}
// 获取缓存的插件
get(key) {
const entry = this.cache.get(key);
if (!entry) {
this.missCount++;
return null;
}
// 检查TTL
if (Date.now() - entry.timestamp > this.ttl) {
this.cache.delete(key);
this.metadata.delete(key);
this.missCount++;
return null;
}
// 更新访问信息
entry.accessCount++;
entry.lastAccess = Date.now();
this.hitCount++;
return entry.plugin;
}
// 检查缓存是否存在
has(key) {
const entry = this.cache.get(key);
if (!entry) {
return false;
}
// 检查TTL
if (Date.now() - entry.timestamp > this.ttl) {
this.cache.delete(key);
this.metadata.delete(key);
return false;
}
return true;
}
// LRU淘汰策略
evictLRU() {
let oldestKey = null;
let oldestTime = Date.now();
for (const [key, entry] of this.cache) {
if (entry.lastAccess < oldestTime) {
oldestTime = entry.lastAccess;
oldestKey = key;
}
}
if (oldestKey) {
this.cache.delete(oldestKey);
this.metadata.delete(oldestKey);
}
}
// 清理过期缓存
cleanup() {
const now = Date.now();
const toDelete = [];
for (const [key, entry] of this.cache) {
if (now - entry.timestamp > this.ttl) {
toDelete.push(key);
}
}
toDelete.forEach(key => {
this.cache.delete(key);
this.metadata.delete(key);
});
return toDelete.length;
}
// 获取缓存统计
getStats() {
const total = this.hitCount + this.missCount;
const hitRate = total > 0 ? (this.hitCount / total * 100).toFixed(2) : 0;
return {
size: this.cache.size,
maxSize: this.maxSize,
hitCount: this.hitCount,
missCount: this.missCount,
hitRate: `${hitRate}%`,
memoryUsage: this.estimateMemoryUsage()
};
}
// 估算内存使用
estimateMemoryUsage() {
let totalSize = 0;
for (const [key, entry] of this.cache) {
// 简单估算,实际应该更精确
totalSize += key.length * 2; // 字符串大小
totalSize += JSON.stringify(entry).length * 2; // 对象大小估算
}
return `${(totalSize / 1024).toFixed(2)} KB`;
}
// 清空缓存
clear() {
this.cache.clear();
this.metadata.clear();
this.hitCount = 0;
this.missCount = 0;
}
}
module.exports = PluginCache;
2. 事件系统优化
事件池和对象复用
javascript
// optimized-event-system.js
class OptimizedEventSystem {
constructor() {
this.listeners = new Map();
this.eventPool = [];
this.maxPoolSize = 100;
this.stats = {
eventsEmitted: 0,
listenersExecuted: 0,
poolHits: 0,
poolMisses: 0
};
}
// 从对象池获取事件对象
getEventObject() {
if (this.eventPool.length > 0) {
this.stats.poolHits++;
return this.eventPool.pop();
}
this.stats.poolMisses++;
return this.createEventObject();
}
// 创建事件对象
createEventObject() {
return {
type: null,
data: null,
timestamp: 0,
source: null,
cancelled: false,
results: [],
// 重置方法
reset() {
this.type = null;
this.data = null;
this.timestamp = 0;
this.source = null;
this.cancelled = false;
this.results.length = 0;
}
};
}
// 回收事件对象到池中
recycleEventObject(eventObj) {
if (this.eventPool.length < this.maxPoolSize) {
eventObj.reset();
this.eventPool.push(eventObj);
}
}
// 优化的事件发射
emit(type, data, source = null) {
const listeners = this.listeners.get(type);
if (!listeners || listeners.length === 0) {
return;
}
// 从池中获取事件对象
const eventObj = this.getEventObject();
eventObj.type = type;
eventObj.data = data;
eventObj.timestamp = Date.now();
eventObj.source = source;
this.stats.eventsEmitted++;
try {
// 批量执行监听器
this.executeBatch(listeners, eventObj);
} finally {
// 回收事件对象
this.recycleEventObject(eventObj);
}
}
// 批量执行监听器
executeBatch(listeners, eventObj) {
const batchSize = 10; // 每批处理10个监听器
for (let i = 0; i < listeners.length; i += batchSize) {
const batch = listeners.slice(i, i + batchSize);
// 同步执行批次
for (const listener of batch) {
if (eventObj.cancelled) break;
try {
listener.callback(eventObj.data, eventObj);
this.stats.listenersExecuted++;
} catch (error) {
console.error('Listener error:', error);
}
}
// 让出控制权,避免阻塞
if (i + batchSize < listeners.length) {
setImmediate(() => {});
}
}
}
// 优化的监听器注册
on(type, callback, options = {}) {
if (!this.listeners.has(type)) {
this.listeners.set(type, []);
}
const listener = {
callback,
priority: options.priority || 0,
once: options.once || false,
id: this.generateId()
};
const listeners = this.listeners.get(type);
// 按优先级插入(使用二分查找优化)
this.insertByPriority(listeners, listener);
return () => this.off(type, listener.id);
}
// 按优先级插入监听器
insertByPriority(listeners, listener) {
let left = 0;
let right = listeners.length;
while (left < right) {
const mid = Math.floor((left + right) / 2);
if (listeners[mid].priority >= listener.priority) {
left = mid + 1;
} else {
right = mid;
}
}
listeners.splice(left, 0, listener);
}
// 移除监听器
off(type, listenerId) {
const listeners = this.listeners.get(type);
if (!listeners) return false;
const index = listeners.findIndex(l => l.id === listenerId);
if (index > -1) {
listeners.splice(index, 1);
// 如果没有监听器了,删除类型
if (listeners.length === 0) {
this.listeners.delete(type);
}
return true;
}
return false;
}
// 生成ID
generateId() {
return Math.random().toString(36).substr(2, 9);
}
// 获取性能统计
getStats() {
return {
...this.stats,
poolSize: this.eventPool.length,
maxPoolSize: this.maxPoolSize,
poolEfficiency: this.stats.poolHits / (this.stats.poolHits + this.stats.poolMisses) * 100,
listenerTypes: this.listeners.size,
totalListeners: Array.from(this.listeners.values()).reduce((sum, arr) => sum + arr.length, 0)
};
}
// 清理资源
cleanup() {
this.listeners.clear();
this.eventPool.length = 0;
this.stats = {
eventsEmitted: 0,
listenersExecuted: 0,
poolHits: 0,
poolMisses: 0
};
}
}
module.exports = OptimizedEventSystem;
3. 内存管理优化
内存监控器
javascript
// memory-monitor.js
class MemoryMonitor {
constructor(options = {}) {
this.options = {
interval: 30000, // 30秒检查一次
threshold: 0.8, // 80%内存使用率阈值
maxHeapSize: 1024 * 1024 * 1024, // 1GB
...options
};
this.monitoring = false;
this.intervalId = null;
this.callbacks = new Set();
this.history = [];
this.maxHistorySize = 100;
}
// 开始监控
start() {
if (this.monitoring) return;
this.monitoring = true;
this.intervalId = setInterval(() => {
this.checkMemory();
}, this.options.interval);
console.log('🔍 Memory monitoring started');
}
// 停止监控
stop() {
if (!this.monitoring) return;
this.monitoring = false;
if (this.intervalId) {
clearInterval(this.intervalId);
this.intervalId = null;
}
console.log('🛑 Memory monitoring stopped');
}
// 检查内存使用情况
checkMemory() {
const memUsage = process.memoryUsage();
const heapUsed = memUsage.heapUsed;
const heapTotal = memUsage.heapTotal;
const external = memUsage.external;
const usage = {
heapUsed,
heapTotal,
external,
rss: memUsage.rss,
heapUsedMB: Math.round(heapUsed / 1024 / 1024),
heapTotalMB: Math.round(heapTotal / 1024 / 1024),
heapUsagePercent: (heapUsed / heapTotal * 100).toFixed(2),
timestamp: Date.now()
};
// 添加到历史记录
this.addToHistory(usage);
// 检查阈值
const usagePercent = heapUsed / this.options.maxHeapSize;
if (usagePercent > this.options.threshold) {
this.triggerWarning(usage, usagePercent);
}
// 通知回调
this.notifyCallbacks(usage);
}
// 添加到历史记录
addToHistory(usage) {
this.history.push(usage);
if (this.history.length > this.maxHistorySize) {
this.history.shift();
}
}
// 触发内存警告
triggerWarning(usage, usagePercent) {
console.warn(`⚠️ High memory usage detected: ${(usagePercent * 100).toFixed(2)}%`);
console.warn(` Heap used: ${usage.heapUsedMB}MB / ${Math.round(this.options.maxHeapSize / 1024 / 1024)}MB`);
// 建议垃圾回收
if (global.gc) {
console.log('🗑️ Triggering garbage collection...');
global.gc();
// 重新检查内存
setTimeout(() => {
const newUsage = process.memoryUsage();
const freed = usage.heapUsed - newUsage.heapUsed;
console.log(`✅ GC completed, freed ${Math.round(freed / 1024 / 1024)}MB`);
}, 100);
}
}
// 注册回调
onMemoryChange(callback) {
this.callbacks.add(callback);
return () => this.callbacks.delete(callback);
}
// 通知回调
notifyCallbacks(usage) {
for (const callback of this.callbacks) {
try {
callback(usage);
} catch (error) {
console.error('Memory monitor callback error:', error);
}
}
}
// 获取内存统计
getStats() {
const current = process.memoryUsage();
if (this.history.length === 0) {
return {
current: {
heapUsedMB: Math.round(current.heapUsed / 1024 / 1024),
heapTotalMB: Math.round(current.heapTotal / 1024 / 1024),
heapUsagePercent: (current.heapUsed / current.heapTotal * 100).toFixed(2)
},
trend: 'no-data'
};
}
const recent = this.history.slice(-10);
const avgUsage = recent.reduce((sum, usage) => sum + usage.heapUsed, 0) / recent.length;
const trend = current.heapUsed > avgUsage * 1.1 ? 'increasing' :
current.heapUsed < avgUsage * 0.9 ? 'decreasing' : 'stable';
return {
current: {
heapUsedMB: Math.round(current.heapUsed / 1024 / 1024),
heapTotalMB: Math.round(current.heapTotal / 1024 / 1024),
heapUsagePercent: (current.heapUsed / current.heapTotal * 100).toFixed(2),
rssMB: Math.round(current.rss / 1024 / 1024),
externalMB: Math.round(current.external / 1024 / 1024)
},
trend,
history: this.history.length,
monitoring: this.monitoring
};
}
// 强制垃圾回收
forceGC() {
if (global.gc) {
const before = process.memoryUsage();
global.gc();
const after = process.memoryUsage();
const freed = before.heapUsed - after.heapUsed;
console.log(`🗑️ Manual GC: freed ${Math.round(freed / 1024 / 1024)}MB`);
return {
before: Math.round(before.heapUsed / 1024 / 1024),
after: Math.round(after.heapUsed / 1024 / 1024),
freed: Math.round(freed / 1024 / 1024)
};
} else {
console.warn('⚠️ Garbage collection not available. Run with --expose-gc flag.');
return null;
}
}
}
module.exports = MemoryMonitor;
开发最佳实践
1. 插件设计原则
单一职责原则
javascript
// 好的示例:职责单一的插件
class LoggerPlugin extends EnhancedPlugin {
constructor() {
super('logger', '1.0.0');
this.logLevel = 'info';
}
async init(context) {
this.context = context;
// 只负责日志记录功能
context.services.register('logger', () => ({
debug: (msg) => this.log('debug', msg),
info: (msg) => this.log('info', msg),
warn: (msg) => this.log('warn', msg),
error: (msg) => this.log('error', msg)
}));
}
log(level, message) {
if (this.shouldLog(level)) {
console.log(`[${level.toUpperCase()}] ${message}`);
}
}
shouldLog(level) {
const levels = ['debug', 'info', 'warn', 'error'];
return levels.indexOf(level) >= levels.indexOf(this.logLevel);
}
}
// 不好的示例:职责过多的插件
class MonolithPlugin extends EnhancedPlugin {
constructor() {
super('monolith', '1.0.0');
}
async init(context) {
// 违反单一职责原则 - 做了太多事情
this.setupLogging();
this.setupDatabase();
this.setupCache();
this.setupAuth();
this.setupNotifications();
}
// ... 大量不相关的方法
}
依赖注入模式
javascript
// dependency-injection-plugin.js
class DatabasePlugin extends EnhancedPlugin {
constructor(options = {}) {
super('database', '1.0.0');
this.options = options;
}
async init(context) {
this.context = context;
// 注册数据库服务
context.services.register('database', (deps) => {
// 依赖注入:需要配置服务和日志服务
const config = deps.config || this.options;
const logger = deps.logger;
return new DatabaseService(config, logger);
}, {
dependencies: ['config', 'logger']
});
}
}
class DatabaseService {
constructor(config, logger) {
this.config = config;
this.logger = logger;
this.connection = null;
}
async connect() {
this.logger?.info('Connecting to database...');
// 连接逻辑
this.connection = { connected: true };
this.logger?.info('Database connected');
}
async query(sql) {
if (!this.connection) {
throw new Error('Database not connected');
}
this.logger?.debug(`Executing query: ${sql}`);
// 查询逻辑
return { results: [] };
}
}
错误处理最佳实践
javascript
// error-handling-plugin.js
class RobustPlugin extends EnhancedPlugin {
constructor() {
super('robust', '1.0.0');
this.retryCount = 0;
this.maxRetries = 3;
}
async init(context) {
this.context = context;
try {
await this.initializeWithRetry();
} catch (error) {
// 记录详细错误信息
this.logError('Initialization failed', error);
// 设置降级模式
this.enableFallbackMode();
// 不要重新抛出错误,让插件系统继续运行
}
}
async initializeWithRetry() {
for (let i = 0; i < this.maxRetries; i++) {
try {
await this.doInitialize();
return; // 成功则返回
} catch (error) {
this.retryCount++;
if (i === this.maxRetries - 1) {
throw error; // 最后一次重试失败则抛出
}
// 指数退避
const delay = Math.pow(2, i) * 1000;
await this.sleep(delay);
}
}
}
async doInitialize() {
// 实际初始化逻辑
// 可能会抛出异常
}
enableFallbackMode() {
this.context.log('Enabling fallback mode for robust plugin');
// 提供基本功能
this.context.services.register('robust', () => ({
isAvailable: () => false,
getStatus: () => 'fallback-mode'
}));
}
logError(message, error) {
const errorInfo = {
message,
error: error.message,
stack: error.stack,
timestamp: new Date().toISOString(),
plugin: this.name,
retryCount: this.retryCount
};
this.context.error('Plugin error:', errorInfo);
}
sleep(ms) {
return new Promise(resolve => setTimeout(resolve, ms));
}
}
2. 性能监控和分析
性能分析器
javascript
// performance-profiler.js
class PerformanceProfiler {
constructor() {
this.profiles = new Map();
this.activeProfiles = new Map();
this.hooks = new Map();
}
// 开始性能分析
start(name, metadata = {}) {
const profile = {
name,
startTime: process.hrtime.bigint(),
startMemory: process.memoryUsage(),
metadata,
children: [],
parent: null
};
// 检查是否有父级分析
const currentProfile = this.getCurrentProfile();
if (currentProfile) {
profile.parent = currentProfile;
currentProfile.children.push(profile);
}
this.activeProfiles.set(name, profile);
return profile;
}
// 结束性能分析
end(name) {
const profile = this.activeProfiles.get(name);
if (!profile) {
console.warn(`No active profile found for: ${name}`);
return null;
}
profile.endTime = process.hrtime.bigint();
profile.endMemory = process.memoryUsage();
profile.duration = Number(profile.endTime - profile.startTime) / 1000000; // 转换为毫秒
profile.memoryDelta = profile.endMemory.heapUsed - profile.startMemory.heapUsed;
this.activeProfiles.delete(name);
this.profiles.set(name, profile);
// 触发钩子
this.triggerHooks('profileComplete', profile);
return profile;
}
// 获取当前活跃的分析
getCurrentProfile() {
const profiles = Array.from(this.activeProfiles.values());
return profiles[profiles.length - 1] || null;
}
// 包装函数进行性能分析
wrap(name, fn, metadata = {}) {
return async (...args) => {
this.start(name, metadata);
try {
const result = await fn(...args);
return result;
} finally {
this.end(name);
}
};
}
// 分析插件方法
profilePlugin(plugin) {
const originalMethods = {};
// 包装主要方法
const methodsToProfile = ['init', 'enable', 'disable', 'destroy'];
methodsToProfile.forEach(methodName => {
if (typeof plugin[methodName] === 'function') {
originalMethods[methodName] = plugin[methodName];
plugin[methodName] = this.wrap(
`${plugin.name}.${methodName}`,
originalMethods[methodName].bind(plugin),
{ plugin: plugin.name, method: methodName }
);
}
});
return () => {
// 恢复原始方法
Object.keys(originalMethods).forEach(methodName => {
plugin[methodName] = originalMethods[methodName];
});
};
}
// 注册钩子
onProfileComplete(callback) {
if (!this.hooks.has('profileComplete')) {
this.hooks.set('profileComplete', []);
}
this.hooks.get('profileComplete').push(callback);
}
// 触发钩子
triggerHooks(event, data) {
const callbacks = this.hooks.get(event);
if (!callbacks) return;
callbacks.forEach(callback => {
try {
callback(data);
} catch (error) {
console.error('Profile hook error:', error);
}
});
}
// 生成性能报告
generateReport() {
const profiles = Array.from(this.profiles.values());
// 按持续时间排序
profiles.sort((a, b) => b.duration - a.duration);
const report = {
summary: {
totalProfiles: profiles.length,
totalDuration: profiles.reduce((sum, p) => sum + p.duration, 0),
averageDuration: profiles.length > 0 ?
profiles.reduce((sum, p) => sum + p.duration, 0) / profiles.length : 0,
slowestOperation: profiles[0]?.name || 'none'
},
topSlowest: profiles.slice(0, 10).map(p => ({
name: p.name,
duration: `${p.duration.toFixed(2)}ms`,
memoryDelta: `${Math.round(p.memoryDelta / 1024)}KB`,
metadata: p.metadata
})),
byPlugin: this.groupByPlugin(profiles),
memoryImpact: profiles
.filter(p => Math.abs(p.memoryDelta) > 1024) // 大于1KB的内存变化
.sort((a, b) => Math.abs(b.memoryDelta) - Math.abs(a.memoryDelta))
.slice(0, 10)
.map(p => ({
name: p.name,
memoryDelta: `${Math.round(p.memoryDelta / 1024)}KB`,
duration: `${p.duration.toFixed(2)}ms`
}))
};
return report;
}
// 按插件分组
groupByPlugin(profiles) {
const byPlugin = {};
profiles.forEach(profile => {
const pluginName = profile.metadata.plugin || 'unknown';
if (!byPlugin[pluginName]) {
byPlugin[pluginName] = {
totalDuration: 0,
operationCount: 0,
operations: []
};
}
byPlugin[pluginName].totalDuration += profile.duration;
byPlugin[pluginName].operationCount++;
byPlugin[pluginName].operations.push({
name: profile.name,
duration: profile.duration,
memoryDelta: profile.memoryDelta
});
});
// 按总持续时间排序
return Object.entries(byPlugin)
.sort(([,a], [,b]) => b.totalDuration - a.totalDuration)
.reduce((obj, [key, value]) => {
obj[key] = {
...value,
averageDuration: value.totalDuration / value.operationCount
};
return obj;
}, {});
}
// 清理分析数据
clear() {
this.profiles.clear();
this.activeProfiles.clear();
}
// 导出分析数据
export() {
return {
profiles: Array.from(this.profiles.entries()),
timestamp: Date.now(),
report: this.generateReport()
};
}
}
module.exports = PerformanceProfiler;
3. 测试策略
插件测试框架
javascript
// plugin-test-framework.js
class PluginTestFramework {
constructor() {
this.testSuites = new Map();
this.mockServices = new Map();
this.testResults = [];
}
// 创建测试套件
describe(pluginName, testFn) {
const suite = new TestSuite(pluginName);
this.testSuites.set(pluginName, suite);
// 执行测试定义
testFn(suite);
return suite;
}
// 运行所有测试
async runAll() {
console.log('🧪 Running plugin tests...\n');
const results = [];
for (const [pluginName, suite] of this.testSuites) {
console.log(`Testing ${pluginName}:`);
const suiteResult = await this.runSuite(suite);
results.push(suiteResult);
this.printSuiteResult(suiteResult);
console.log('');
}
this.printSummary(results);
return results;
}
// 运行测试套件
async runSuite(suite) {
const result = {
pluginName: suite.pluginName,
tests: [],
passed: 0,
failed: 0,
skipped: 0,
duration: 0
};
const startTime = Date.now();
for (const test of suite.tests) {
const testResult = await this.runTest(test, suite);
result.tests.push(testResult);
if (testResult.status === 'passed') {
result.passed++;
} else if (testResult.status === 'failed') {
result.failed++;
} else {
result.skipped++;
}
}
result.duration = Date.now() - startTime;
return result;
}
// 运行单个测试
async runTest(test, suite) {
const result = {
name: test.name,
status: 'passed',
error: null,
duration: 0
};
const startTime = Date.now();
try {
// 设置测试环境
const context = this.createTestContext(suite);
// 运行测试
await test.fn(context);
} catch (error) {
result.status = 'failed';
result.error = error.message;
}
result.duration = Date.now() - startTime;
return result;
}
// 创建测试上下文
createTestContext(suite) {
return {
// 模拟插件管理器
pluginManager: this.createMockPluginManager(),
// 模拟服务
services: this.mockServices,
// 断言方法
expect: this.createExpectAPI(),
// 模拟方法
mock: this.createMockAPI(),
// 测试工具
utils: {
sleep: (ms) => new Promise(resolve => setTimeout(resolve, ms)),
createPlugin: (name, options) => this.createTestPlugin(name, options)
}
};
}
// 创建模拟插件管理器
createMockPluginManager() {
return {
plugins: new Map(),
register: async (plugin) => {
this.plugins.set(plugin.name, plugin);
},
getPlugin: (name) => {
return this.plugins.get(name);
},
initPlugin: async (name) => {
const plugin = this.plugins.get(name);
if (plugin && plugin.init) {
await plugin.init(this.createTestContext());
}
}
};
}
// 创建断言API
createExpectAPI() {
return (actual) => ({
toBe: (expected) => {
if (actual !== expected) {
throw new Error(`Expected ${actual} to be ${expected}`);
}
},
toEqual: (expected) => {
if (JSON.stringify(actual) !== JSON.stringify(expected)) {
throw new Error(`Expected ${JSON.stringify(actual)} to equal ${JSON.stringify(expected)}`);
}
},
toThrow: async (fn) => {
let threw = false;
try {
await fn();
} catch {
threw = true;
}
if (!threw) {
throw new Error('Expected function to throw');
}
},
toBeDefined: () => {
if (actual === undefined) {
throw new Error('Expected value to be defined');
}
},
toBeNull: () => {
if (actual !== null) {
throw new Error('Expected value to be null');
}
}
});
}
// 创建模拟API
createMockAPI() {
return {
fn: (implementation) => {
const mockFn = implementation || (() => {});
mockFn.calls = [];
const wrappedFn = (...args) => {
mockFn.calls.push(args);
return mockFn(...args);
};
wrappedFn.calls = mockFn.calls;
return wrappedFn;
},
service: (name, implementation) => {
this.mockServices.set(name, implementation);
}
};
}
// 创建测试插件
createTestPlugin(name, options = {}) {
return {
name,
version: '1.0.0',
...options,
init: options.init || (async () => {}),
enable: options.enable || (async () => {}),
disable: options.disable || (async () => {})
};
}
// 打印套件结果
printSuiteResult(result) {
result.tests.forEach(test => {
const status = test.status === 'passed' ? '✅' : '❌';
const duration = `(${test.duration}ms)`;
console.log(` ${status} ${test.name} ${duration}`);
if (test.error) {
console.log(` Error: ${test.error}`);
}
});
const summary = `${result.passed} passed, ${result.failed} failed, ${result.skipped} skipped`;
console.log(` Summary: ${summary} (${result.duration}ms)`);
}
// 打印总结
printSummary(results) {
const totalPassed = results.reduce((sum, r) => sum + r.passed, 0);
const totalFailed = results.reduce((sum, r) => sum + r.failed, 0);
const totalSkipped = results.reduce((sum, r) => sum + r.skipped, 0);
const totalDuration = results.reduce((sum, r) => sum + r.duration, 0);
console.log('📊 Test Summary:');
console.log(` Total: ${totalPassed + totalFailed + totalSkipped} tests`);
console.log(` Passed: ${totalPassed}`);
console.log(` Failed: ${totalFailed}`);
console.log(` Skipped: ${totalSkipped}`);
console.log(` Duration: ${totalDuration}ms`);
if (totalFailed > 0) {
console.log('\n❌ Some tests failed!');
} else {
console.log('\n✅ All tests passed!');
}
}
}
class TestSuite {
constructor(pluginName) {
this.pluginName = pluginName;
this.tests = [];
this.beforeEachFn = null;
this.afterEachFn = null;
}
// 添加测试
it(name, testFn) {
this.tests.push({ name, fn: testFn });
}
// 设置前置操作
beforeEach(fn) {
this.beforeEachFn = fn;
}
// 设置后置操作
afterEach(fn) {
this.afterEachFn = fn;
}
}
module.exports = PluginTestFramework;
综合优化示例
让我们创建一个集成了所有优化技术的插件管理器:
优化版插件管理器
javascript
// optimized-plugin-manager.js
const EnterprisePluginManager = require('../chapter-06/enterprise-plugin-manager');
const LazyPluginLoader = require('./lazy-plugin-loader');
const PluginCache = require('./plugin-cache');
const OptimizedEventSystem = require('./optimized-event-system');
const MemoryMonitor = require('./memory-monitor');
const PerformanceProfiler = require('./performance-profiler');
class OptimizedPluginManager extends EnterprisePluginManager {
constructor(options = {}) {
super(options);
// 初始化优化组件
this.lazyLoader = new LazyPluginLoader(this);
this.cache = new PluginCache(options.cache);
this.optimizedEvents = new OptimizedEventSystem();
this.memoryMonitor = new MemoryMonitor(options.memory);
this.profiler = new PerformanceProfiler();
// 替换事件系统
this.replaceEventSystem();
// 启用性能监控
this.enablePerformanceMonitoring();
// 启用内存监控
this.memoryMonitor.start();
// 设置清理定时器
this.setupCleanupTimer();
}
// 替换事件系统
replaceEventSystem() {
// 保存原有监听器
const originalListeners = this.listeners || new Map();
// 迁移到优化的事件系统
for (const [event, listeners] of originalListeners) {
listeners.forEach(listener => {
this.optimizedEvents.on(event, listener.callback, {
priority: listener.priority || 0,
once: listener.once || false
});
});
}
// 替换事件方法
this.on = this.optimizedEvents.on.bind(this.optimizedEvents);
this.emit = this.optimizedEvents.emit.bind(this.optimizedEvents);
this.off = this.optimizedEvents.off.bind(this.optimizedEvents);
}
// 启用性能监控
enablePerformanceMonitoring() {
// 监控插件生命周期方法
this.profiler.onProfileComplete((profile) => {
if (profile.duration > 1000) { // 超过1秒的操作
console.warn(`⚠️ Slow operation detected: ${profile.name} (${profile.duration.toFixed(2)}ms)`);
}
});
// 监控内存使用
this.memoryMonitor.onMemoryChange((usage) => {
if (parseFloat(usage.heapUsagePercent) > 80) {
console.warn(`⚠️ High memory usage: ${usage.heapUsagePercent}%`);
// 触发缓存清理
this.cache.cleanup();
}
});
}
// 设置清理定时器
setupCleanupTimer() {
// 每5分钟清理一次
this.cleanupTimer = setInterval(() => {
this.performMaintenance();
}, 5 * 60 * 1000);
}
// 执行维护任务
performMaintenance() {
console.log('🧹 Performing maintenance...');
// 清理缓存
const cleanedCache = this.cache.cleanup();
// 清理事件池
if (this.optimizedEvents.eventPool.length > 50) {
this.optimizedEvents.eventPool.length = 25; // 保留一半
}
// 强制垃圾回收(如果可用)
if (global.gc && Math.random() < 0.1) { // 10%的概率
this.memoryMonitor.forceGC();
}
console.log(`✅ Maintenance completed. Cleaned ${cleanedCache} cache entries.`);
}
// 重写插件注册方法,添加缓存和性能监控
async register(plugin, options = {}) {
const cacheKey = `plugin:${plugin.name}:${plugin.version}`;
// 检查缓存
const cached = this.cache.get(cacheKey);
if (cached && !options.forceReload) {
console.log(`📦 Loading plugin ${plugin.name} from cache`);
return cached;
}
// 性能分析
this.profiler.start(`register:${plugin.name}`, {
plugin: plugin.name,
version: plugin.version
});
try {
// 检查是否应该懒加载
if (options.lazy) {
this.lazyLoader.registerLazy(plugin.name, () => plugin, options.lazyConditions);
return this;
}
// 包装插件方法进行性能监控
const restoreProfiler = this.profiler.profilePlugin(plugin);
// 调用父类方法
const result = await super.register(plugin, options);
// 缓存结果
this.cache.set(cacheKey, result, {
plugin: plugin.name,
version: plugin.version,
registeredAt: Date.now()
});
return result;
} finally {
this.profiler.end(`register:${plugin.name}`);
}
}
// 重写插件初始化方法
async initPlugin(name) {
// 检查懒加载
const lazyPlugin = await this.lazyLoader.checkAndLoad(name, {
trigger: 'init',
features: this.configManager.getConfig('features', {})
});
if (lazyPlugin) {
return lazyPlugin;
}
// 性能分析
this.profiler.start(`init:${name}`, { plugin: name });
try {
return await super.initPlugin(name);
} finally {
this.profiler.end(`init:${name}`);
}
}
// 批量操作优化
async initAll() {
console.log('🚀 Initializing all plugins with optimization...');
const plugins = Array.from(this.plugins.keys());
const batchSize = 5; // 每批处理5个插件
for (let i = 0; i < plugins.length; i += batchSize) {
const batch = plugins.slice(i, i + batchSize);
// 并行初始化批次
const promises = batch.map(name => this.initPlugin(name).catch(error => {
console.error(`Failed to init plugin ${name}:`, error);
return null;
}));
await Promise.all(promises);
// 让出控制权
await new Promise(resolve => setImmediate(resolve));
}
console.log('✅ All plugins initialized');
}
// 获取优化统计信息
getOptimizationStats() {
return {
cache: this.cache.getStats(),
events: this.optimizedEvents.getStats(),
memory: this.memoryMonitor.getStats(),
performance: this.profiler.generateReport(),
lazyLoading: this.lazyLoader.getLoadStatus()
};
}
// 生成性能报告
generatePerformanceReport() {
const stats = this.getOptimizationStats();
console.log('\n📊 Performance Report:');
console.log('='.repeat(50));
// 缓存统计
console.log(`\n🗄️ Cache Statistics:`);
console.log(` Hit Rate: ${stats.cache.hitRate}`);
console.log(` Size: ${stats.cache.size}/${stats.cache.maxSize}`);
console.log(` Memory Usage: ${stats.cache.memoryUsage}`);
// 事件统计
console.log(`\n📡 Event System:`);
console.log(` Events Emitted: ${stats.events.eventsEmitted}`);
console.log(` Listeners Executed: ${stats.events.listenersExecuted}`);
console.log(` Pool Efficiency: ${stats.events.poolEfficiency.toFixed(2)}%`);
// 内存统计
console.log(`\n💾 Memory Usage:`);
console.log(` Heap Used: ${stats.memory.current.heapUsedMB}MB`);
console.log(` Heap Usage: ${stats.memory.current.heapUsagePercent}%`);
console.log(` Trend: ${stats.memory.trend}`);
// 性能统计
console.log(`\n⚡ Performance:`);
console.log(` Total Operations: ${stats.performance.summary.totalProfiles}`);
console.log(` Average Duration: ${stats.performance.summary.averageDuration.toFixed(2)}ms`);
console.log(` Slowest Operation: ${stats.performance.summary.slowestOperation}`);
// 懒加载统计
const lazyStats = Object.values(stats.lazyLoading);
const loadedCount = lazyStats.filter(s => s.loaded).length;
console.log(`\n🔄 Lazy Loading:`);
console.log(` Registered: ${lazyStats.length}`);
console.log(` Loaded: ${loadedCount}`);
console.log(` Loading: ${lazyStats.filter(s => s.loading).length}`);
console.log('='.repeat(50));
return stats;
}
// 清理资源
async cleanup() {
console.log('🧹 Cleaning up optimized plugin manager...');
// 停止定时器
if (this.cleanupTimer) {
clearInterval(this.cleanupTimer);
}
// 停止内存监控
this.memoryMonitor.stop();
// 清理缓存
this.cache.clear();
// 清理事件系统
this.optimizedEvents.cleanup();
// 清理性能分析器
this.profiler.clear();
// 调用父类清理
await super.cleanup();
console.log('✅ Cleanup completed');
}
}
module.exports = OptimizedPluginManager;
使用示例
javascript
// optimization-example.js
const OptimizedPluginManager = require('./optimized-plugin-manager');
const PluginTestFramework = require('./plugin-test-framework');
// 创建测试插件
class TestPlugin {
constructor(name, delay = 0) {
this.name = name;
this.version = '1.0.0';
this.delay = delay;
}
async init(context) {
// 模拟初始化延迟
if (this.delay > 0) {
await new Promise(resolve => setTimeout(resolve, this.delay));
}
context.log(`${this.name} initialized`);
}
async enable() {
console.log(`${this.name} enabled`);
}
}
async function runOptimizationExample() {
console.log('🚀 Running optimization example...\n');
// 创建优化的插件管理器
const pluginManager = new OptimizedPluginManager({
cache: {
maxSize: 50,
ttl: 300000 // 5分钟
},
memory: {
threshold: 0.7, // 70%阈值
interval: 10000 // 10秒检查
}
});
try {
// 注册多个插件
console.log('📦 Registering plugins...');
// 普通插件
await pluginManager.register(new TestPlugin('fast-plugin', 100));
await pluginManager.register(new TestPlugin('medium-plugin', 500));
// 懒加载插件
await pluginManager.register(new TestPlugin('slow-plugin', 2000), {
lazy: true,
lazyConditions: {
trigger: 'heavy-operation',
feature: 'advanced-features'
}
});
// 缓存测试 - 重复注册相同插件
await pluginManager.register(new TestPlugin('fast-plugin', 100));
console.log('\n⚡ Initializing plugins...');
await pluginManager.initAll();
console.log('\n🔄 Enabling plugins...');
await pluginManager.enableAll();
// 测试事件系统性能
console.log('\n📡 Testing event system performance...');
const eventCount = 1000;
pluginManager.on('test-event', (data) => {
// 模拟事件处理
});
const startTime = Date.now();
for (let i = 0; i < eventCount; i++) {
pluginManager.emit('test-event', { index: i });
}
const eventTime = Date.now() - startTime;
console.log(` Emitted ${eventCount} events in ${eventTime}ms`);
// 触发懒加载
console.log('\n🔄 Triggering lazy loading...');
await pluginManager.lazyLoader.checkAndLoad('slow-plugin', {
trigger: 'heavy-operation',
features: { 'advanced-features': true }
});
// 生成性能报告
console.log('\n📊 Generating performance report...');
pluginManager.generatePerformanceReport();
// 运行插件测试
console.log('\n🧪 Running plugin tests...');
const testFramework = new PluginTestFramework();
testFramework.describe('fast-plugin', (suite) => {
suite.it('should initialize quickly', async (context) => {
const plugin = context.utils.createPlugin('test-fast', { delay: 50 });
const start = Date.now();
await plugin.init(context);
const duration = Date.now() - start;
context.expect(duration).toBe(duration < 100);
});
suite.it('should be enabled', async (context) => {
const plugin = context.pluginManager.getPlugin('fast-plugin');
context.expect(plugin).toBeDefined();
});
});
await testFramework.runAll();
// 保持运行一段时间以观察内存监控
console.log('\n⏱️ Running for 30 seconds to demonstrate monitoring...');
console.log(' (Watch for memory warnings and maintenance messages)');
await new Promise(resolve => setTimeout(resolve, 30000));
} catch (error) {
console.error('❌ Error:', error);
} finally {
await pluginManager.cleanup();
}
}
// 运行示例
if (require.main === module) {
runOptimizationExample().catch(console.error);
}
module.exports = { runOptimizationExample };
小结
在这一章中,我们深入探讨了插件系统的性能优化和开发最佳实践:
性能优化技术
- 懒加载机制:按需加载插件,减少启动时间
- 缓存系统:缓存插件实例和计算结果
- 事件系统优化:对象池、批量处理、优先级队列
- 内存管理:监控、清理、垃圾回收
开发最佳实践
- 设计原则:单一职责、依赖注入、错误处理
- 性能监控:分析器、统计、报告
- 测试策略:单元测试、集成测试、性能测试
关键收获
- 性能优化是持续过程:需要监控、分析、改进
- 平衡功能与性能:不要过度优化,关注关键路径
- 测试驱动开发:确保优化不破坏功能
- 监控和可观测性:及时发现和解决问题
这些优化技术和最佳实践能够显著提升插件系统的性能和稳定性,让它能够在生产环境中高效运行。
在下一章中,我们将讨论插件系统的调试和测试策略。
练习题
- 实现一个插件的A/B测试系统,支持灰度发布
- 创建一个插件性能基准测试套件
- 设计一个插件系统的监控仪表板
下一章预告:我们将探讨插件系统的调试技巧和全面的测试策略。