Skip to content

性能分析工具

🎯 学习目标

  • 掌握Node.js性能分析工具的使用
  • 学会识别和诊断性能瓶颈
  • 理解内存泄漏检测和CPU分析
  • 了解性能监控和优化策略

📚 核心概念

性能分析基础

javascript
// 性能分析核心概念
const performanceAnalysisConcepts = {
  metrics: {
    cpu: {
      description: 'CPU使用率分析',
      indicators: ['用户时间', '系统时间', '空闲时间', '等待时间'],
      tools: ['perf', 'top', 'htop', 'node --prof']
    },
    memory: {
      description: '内存使用分析',
      indicators: ['堆内存', '栈内存', '外部内存', 'GC频率'],
      tools: ['heapdump', 'memwatch', 'clinic.js']
    },
    io: {
      description: 'I/O性能分析',
      indicators: ['磁盘读写', '网络延迟', '文件系统操作'],
      tools: ['iotop', 'netstat', 'lsof']
    },
    eventLoop: {
      description: '事件循环分析',
      indicators: ['延迟', '阻塞', '队列长度', '处理时间'],
      tools: ['clinic.js', '@nodejs/clinic-doctor']
    }
  },
  profiling: {
    types: ['CPU分析', '内存分析', '火焰图', '调用图'],
    approaches: ['采样分析', '插桩分析', '统计分析']
  }
};

console.log('性能分析概念:', performanceAnalysisConcepts);

🛠️ 内置性能监控工具

基础性能监控器

javascript
// basic-performance-monitor.js
const { performance, PerformanceObserver } = require('perf_hooks');
const EventEmitter = require('events');

class BasicPerformanceMonitor extends EventEmitter {
  constructor(options = {}) {
    super();
    
    this.options = {
      enableCPU: options.enableCPU !== false,
      enableMemory: options.enableMemory !== false,
      enableEventLoop: options.enableEventLoop !== false,
      enableGC: options.enableGC !== false,
      interval: options.interval || 1000,
      ...options
    };
    
    this.metrics = {
      cpu: [],
      memory: [],
      eventLoop: [],
      gc: []
    };
    
    this.observers = [];
    this.timers = [];
    this.isMonitoring = false;
  }

  start() {
    if (this.isMonitoring) {
      console.warn('⚠️ 性能监控已在运行');
      return;
    }

    console.log('🔍 启动性能监控...');
    this.isMonitoring = true;

    if (this.options.enableCPU) {
      this.startCPUMonitoring();
    }

    if (this.options.enableMemory) {
      this.startMemoryMonitoring();
    }

    if (this.options.enableEventLoop) {
      this.startEventLoopMonitoring();
    }

    if (this.options.enableGC) {
      this.startGCMonitoring();
    }

    console.log('✅ 性能监控已启动');
  }

  stop() {
    if (!this.isMonitoring) {
      return;
    }

    console.log('⏹️ 停止性能监控...');
    this.isMonitoring = false;

    // 清理定时器
    this.timers.forEach(timer => clearInterval(timer));
    this.timers = [];

    // 断开观察器
    this.observers.forEach(observer => observer.disconnect());
    this.observers = [];

    console.log('✅ 性能监控已停止');
  }

  startCPUMonitoring() {
    const measureCPU = () => {
      const startTime = process.hrtime.bigint();
      const startUsage = process.cpuUsage();
      
      setTimeout(() => {
        const endTime = process.hrtime.bigint();
        const endUsage = process.cpuUsage(startUsage);
        const duration = Number(endTime - startTime) / 1000000; // 毫秒
        
        const cpuMetric = {
          timestamp: Date.now(),
          user: (endUsage.user / 1000) / duration * 100, // 转换为百分比
          system: (endUsage.system / 1000) / duration * 100,
          total: ((endUsage.user + endUsage.system) / 1000) / duration * 100
        };
        
        this.metrics.cpu.push(cpuMetric);
        this.trimMetrics('cpu');
        
        this.emit('cpu', cpuMetric);
      }, 100);
    };

    const timer = setInterval(measureCPU, this.options.interval);
    this.timers.push(timer);
  }

  startMemoryMonitoring() {
    const measureMemory = () => {
      const memUsage = process.memoryUsage();
      
      const memoryMetric = {
        timestamp: Date.now(),
        heapUsed: memUsage.heapUsed,
        heapTotal: memUsage.heapTotal,
        external: memUsage.external,
        rss: memUsage.rss,
        arrayBuffers: memUsage.arrayBuffers || 0,
        heapUsedMB: (memUsage.heapUsed / 1024 / 1024).toFixed(2),
        heapTotalMB: (memUsage.heapTotal / 1024 / 1024).toFixed(2),
        utilization: (memUsage.heapUsed / memUsage.heapTotal * 100).toFixed(2)
      };
      
      this.metrics.memory.push(memoryMetric);
      this.trimMetrics('memory');
      
      this.emit('memory', memoryMetric);
    };

    const timer = setInterval(measureMemory, this.options.interval);
    this.timers.push(timer);
  }

  startEventLoopMonitoring() {
    const measureEventLoop = () => {
      const start = process.hrtime.bigint();
      
      setImmediate(() => {
        const lag = Number(process.hrtime.bigint() - start) / 1000000; // 毫秒
        
        const eventLoopMetric = {
          timestamp: Date.now(),
          lag: lag
        };
        
        this.metrics.eventLoop.push(eventLoopMetric);
        this.trimMetrics('eventLoop');
        
        this.emit('eventLoop', eventLoopMetric);
        
        if (lag > 10) {
          this.emit('eventLoopLag', { lag, threshold: 10 });
        }
      });
    };

    const timer = setInterval(measureEventLoop, this.options.interval);
    this.timers.push(timer);
  }

  startGCMonitoring() {
    const observer = new PerformanceObserver((list) => {
      const entries = list.getEntries();
      
      entries.forEach(entry => {
        if (entry.entryType === 'gc') {
          const gcMetric = {
            timestamp: entry.startTime + entry.timeOrigin,
            duration: entry.duration,
            kind: entry.detail?.kind || 'unknown',
            type: this.getGCTypeName(entry.detail?.kind),
            flags: entry.detail?.flags || 0
          };
          
          this.metrics.gc.push(gcMetric);
          this.trimMetrics('gc');
          
          this.emit('gc', gcMetric);
          
          if (gcMetric.duration > 50) {
            this.emit('longGC', gcMetric);
          }
        }
      });
    });

    try {
      observer.observe({ entryTypes: ['gc'] });
      this.observers.push(observer);
    } catch (error) {
      console.warn('⚠️ GC监控不可用:', error.message);
    }
  }

  getGCTypeName(kind) {
    const gcTypes = {
      1: 'Scavenge',
      2: 'Mark-Sweep-Compact',
      4: 'Incremental-Marking',
      8: 'Weak-Processing',
      16: 'Full-GC'
    };

    return gcTypes[kind] || `Unknown(${kind})`;
  }

  trimMetrics(type) {
    const maxEntries = 1000;
    if (this.metrics[type].length > maxEntries) {
      this.metrics[type] = this.metrics[type].slice(-maxEntries);
    }
  }

  // 获取性能摘要
  getSummary() {
    const now = Date.now();
    const timeWindow = 60000; // 1分钟

    const summary = {
      timestamp: now,
      timeWindow: '1分钟',
      cpu: this.getCPUSummary(timeWindow),
      memory: this.getMemorySummary(timeWindow),
      eventLoop: this.getEventLoopSummary(timeWindow),
      gc: this.getGCSummary(timeWindow)
    };

    return summary;
  }

  getCPUSummary(timeWindow) {
    const recentCPU = this.getRecentMetrics('cpu', timeWindow);
    
    if (recentCPU.length === 0) {
      return null;
    }

    const avgUser = recentCPU.reduce((sum, m) => sum + m.user, 0) / recentCPU.length;
    const avgSystem = recentCPU.reduce((sum, m) => sum + m.system, 0) / recentCPU.length;
    const avgTotal = recentCPU.reduce((sum, m) => sum + m.total, 0) / recentCPU.length;
    const maxTotal = Math.max(...recentCPU.map(m => m.total));

    return {
      average: {
        user: avgUser.toFixed(2) + '%',
        system: avgSystem.toFixed(2) + '%',
        total: avgTotal.toFixed(2) + '%'
      },
      peak: maxTotal.toFixed(2) + '%',
      samples: recentCPU.length
    };
  }

  getMemorySummary(timeWindow) {
    const recentMemory = this.getRecentMetrics('memory', timeWindow);
    
    if (recentMemory.length === 0) {
      return null;
    }

    const latest = recentMemory[recentMemory.length - 1];
    const avgHeapUsed = recentMemory.reduce((sum, m) => sum + m.heapUsed, 0) / recentMemory.length;
    const maxHeapUsed = Math.max(...recentMemory.map(m => m.heapUsed));
    const trend = this.calculateMemoryTrend(recentMemory);

    return {
      current: {
        heapUsed: latest.heapUsedMB + 'MB',
        heapTotal: latest.heapTotalMB + 'MB',
        utilization: latest.utilization + '%',
        rss: (latest.rss / 1024 / 1024).toFixed(2) + 'MB'
      },
      average: {
        heapUsed: (avgHeapUsed / 1024 / 1024).toFixed(2) + 'MB'
      },
      peak: {
        heapUsed: (maxHeapUsed / 1024 / 1024).toFixed(2) + 'MB'
      },
      trend: trend > 0 ? `+${(trend / 1024 / 1024).toFixed(2)}MB` : `${(trend / 1024 / 1024).toFixed(2)}MB`,
      samples: recentMemory.length
    };
  }

  getEventLoopSummary(timeWindow) {
    const recentEventLoop = this.getRecentMetrics('eventLoop', timeWindow);
    
    if (recentEventLoop.length === 0) {
      return null;
    }

    const avgLag = recentEventLoop.reduce((sum, m) => sum + m.lag, 0) / recentEventLoop.length;
    const maxLag = Math.max(...recentEventLoop.map(m => m.lag));
    const highLagCount = recentEventLoop.filter(m => m.lag > 10).length;

    return {
      average: avgLag.toFixed(2) + 'ms',
      peak: maxLag.toFixed(2) + 'ms',
      highLagEvents: highLagCount,
      samples: recentEventLoop.length
    };
  }

  getGCSummary(timeWindow) {
    const recentGC = this.getRecentMetrics('gc', timeWindow);
    
    if (recentGC.length === 0) {
      return null;
    }

    const totalTime = recentGC.reduce((sum, m) => sum + m.duration, 0);
    const avgDuration = totalTime / recentGC.length;
    const maxDuration = Math.max(...recentGC.map(m => m.duration));
    const typeCount = {};

    recentGC.forEach(gc => {
      typeCount[gc.type] = (typeCount[gc.type] || 0) + 1;
    });

    return {
      count: recentGC.length,
      totalTime: totalTime.toFixed(2) + 'ms',
      average: avgDuration.toFixed(2) + 'ms',
      peak: maxDuration.toFixed(2) + 'ms',
      types: typeCount
    };
  }

  getRecentMetrics(type, timeWindow) {
    const now = Date.now();
    return this.metrics[type].filter(m => now - m.timestamp <= timeWindow);
  }

  calculateMemoryTrend(memoryData) {
    if (memoryData.length < 2) return 0;
    
    const firstHalf = memoryData.slice(0, Math.floor(memoryData.length / 2));
    const secondHalf = memoryData.slice(Math.floor(memoryData.length / 2));
    
    const firstAvg = firstHalf.reduce((sum, m) => sum + m.heapUsed, 0) / firstHalf.length;
    const secondAvg = secondHalf.reduce((sum, m) => sum + m.heapUsed, 0) / secondHalf.length;
    
    return secondAvg - firstAvg;
  }

  // 生成性能报告
  generateReport() {
    const summary = this.getSummary();
    
    console.log('\n📊 性能监控报告');
    console.log('='.repeat(50));
    console.log(`时间窗口: ${summary.timeWindow}`);
    
    if (summary.cpu) {
      console.log('\n🖥️ CPU使用率:');
      console.log(`  平均: 用户=${summary.cpu.average.user}, 系统=${summary.cpu.average.system}, 总计=${summary.cpu.average.total}`);
      console.log(`  峰值: ${summary.cpu.peak}`);
      console.log(`  样本数: ${summary.cpu.samples}`);
    }
    
    if (summary.memory) {
      console.log('\n💾 内存使用:');
      console.log(`  当前: 堆=${summary.memory.current.heapUsed}/${summary.memory.current.heapTotal} (${summary.memory.current.utilization}), RSS=${summary.memory.current.rss}`);
      console.log(`  平均堆使用: ${summary.memory.average.heapUsed}`);
      console.log(`  峰值堆使用: ${summary.memory.peak.heapUsed}`);
      console.log(`  趋势: ${summary.memory.trend}`);
    }
    
    if (summary.eventLoop) {
      console.log('\n⚡ 事件循环:');
      console.log(`  平均延迟: ${summary.eventLoop.average}`);
      console.log(`  最大延迟: ${summary.eventLoop.peak}`);
      console.log(`  高延迟事件: ${summary.eventLoop.highLagEvents}`);
    }
    
    if (summary.gc) {
      console.log('\n🗑️ 垃圾收集:');
      console.log(`  GC次数: ${summary.gc.count}`);
      console.log(`  总时间: ${summary.gc.totalTime}`);
      console.log(`  平均时间: ${summary.gc.average}`);
      console.log(`  最长时间: ${summary.gc.peak}`);
      console.log(`  类型分布: ${JSON.stringify(summary.gc.types)}`);
    }
    
    return summary;
  }

  // 检测性能异常
  detectAnomalies() {
    const anomalies = [];
    const summary = this.getSummary();
    
    // CPU异常检测
    if (summary.cpu) {
      const cpuTotal = parseFloat(summary.cpu.average.total);
      if (cpuTotal > 80) {
        anomalies.push({
          type: 'cpu',
          severity: 'high',
          message: `CPU使用率过高: ${summary.cpu.average.total}`,
          value: cpuTotal
        });
      }
    }
    
    // 内存异常检测
    if (summary.memory) {
      const utilization = parseFloat(summary.memory.current.utilization);
      if (utilization > 90) {
        anomalies.push({
          type: 'memory',
          severity: 'high',
          message: `内存利用率过高: ${summary.memory.current.utilization}`,
          value: utilization
        });
      }
      
      const trendMB = parseFloat(summary.memory.trend.replace(/[^\d.-]/g, ''));
      if (trendMB > 10) {
        anomalies.push({
          type: 'memory',
          severity: 'medium',
          message: `内存持续增长: ${summary.memory.trend}`,
          value: trendMB
        });
      }
    }
    
    // 事件循环异常检测
    if (summary.eventLoop) {
      const avgLag = parseFloat(summary.eventLoop.average);
      if (avgLag > 50) {
        anomalies.push({
          type: 'eventLoop',
          severity: 'high',
          message: `事件循环延迟过高: ${summary.eventLoop.average}`,
          value: avgLag
        });
      }
    }
    
    // GC异常检测
    if (summary.gc) {
      const avgGCTime = parseFloat(summary.gc.average);
      if (avgGCTime > 100) {
        anomalies.push({
          type: 'gc',
          severity: 'medium',
          message: `GC平均时间过长: ${summary.gc.average}`,
          value: avgGCTime
        });
      }
    }
    
    return anomalies;
  }
}

module.exports = BasicPerformanceMonitor;

高级性能分析器

javascript
// advanced-performance-profiler.js
const fs = require('fs').promises;
const path = require('path');
const { performance, PerformanceObserver } = require('perf_hooks');

class AdvancedPerformanceProfiler {
  constructor(options = {}) {
    this.options = {
      outputDir: options.outputDir || './performance-reports',
      enableFlameGraph: options.enableFlameGraph !== false,
      sampleInterval: options.sampleInterval || 1000,
      profilingDuration: options.profilingDuration || 60000,
      ...options
    };
    
    this.profilers = new Map();
    this.isActive = false;
    this.startTime = null;
    this.samples = [];
  }

  async start() {
    if (this.isActive) {
      throw new Error('性能分析器已在运行');
    }

    console.log('🔍 启动高级性能分析器...');
    this.isActive = true;
    this.startTime = Date.now();

    // 确保输出目录存在
    await this.ensureOutputDir();

    // 启动各种分析器
    this.startCPUProfiling();
    this.startMemoryProfiling();
    this.startFunctionProfiling();
    this.startCustomMetrics();

    console.log(`✅ 性能分析器已启动,将运行 ${this.options.profilingDuration}ms`);

    // 设置自动停止
    setTimeout(() => {
      if (this.isActive) {
        this.stop();
      }
    }, this.options.profilingDuration);
  }

  async stop() {
    if (!this.isActive) {
      return;
    }

    console.log('⏹️ 停止性能分析器...');
    this.isActive = false;

    // 停止所有分析器
    for (const [name, profiler] of this.profilers) {
      if (profiler.stop) {
        profiler.stop();
      }
    }

    // 生成报告
    await this.generateReports();

    console.log('✅ 性能分析完成');
  }

  async ensureOutputDir() {
    try {
      await fs.mkdir(this.options.outputDir, { recursive: true });
    } catch (error) {
      console.error('创建输出目录失败:', error);
    }
  }

  startCPUProfiling() {
    const cpuSamples = [];
    
    const sampleCPU = () => {
      if (!this.isActive) return;

      const startUsage = process.cpuUsage();
      const startTime = process.hrtime.bigint();
      
      setTimeout(() => {
        const endUsage = process.cpuUsage(startUsage);
        const endTime = process.hrtime.bigint();
        const duration = Number(endTime - startTime) / 1000000;
        
        const sample = {
          timestamp: Date.now(),
          user: (endUsage.user / 1000) / duration * 100,
          system: (endUsage.system / 1000) / duration * 100,
          duration: duration
        };
        
        cpuSamples.push(sample);
        
        // 继续采样
        setTimeout(sampleCPU, this.options.sampleInterval);
      }, 100);
    };

    sampleCPU();

    this.profilers.set('cpu', {
      samples: cpuSamples,
      stop: () => {
        console.log(`📊 CPU采样完成: ${cpuSamples.length} 个样本`);
      }
    });
  }

  startMemoryProfiling() {
    const memorySamples = [];
    const gcEvents = [];
    
    // 内存采样
    const sampleMemory = () => {
      if (!this.isActive) return;

      const usage = process.memoryUsage();
      const sample = {
        timestamp: Date.now(),
        ...usage,
        heapUtilization: (usage.heapUsed / usage.heapTotal) * 100
      };
      
      memorySamples.push(sample);
      
      setTimeout(sampleMemory, this.options.sampleInterval);
    };

    sampleMemory();

    // GC事件监听
    const gcObserver = new PerformanceObserver((list) => {
      list.getEntries().forEach(entry => {
        if (entry.entryType === 'gc') {
          gcEvents.push({
            timestamp: entry.startTime + entry.timeOrigin,
            duration: entry.duration,
            kind: entry.detail?.kind,
            type: this.getGCTypeName(entry.detail?.kind)
          });
        }
      });
    });

    try {
      gcObserver.observe({ entryTypes: ['gc'] });
    } catch (error) {
      console.warn('GC监控不可用:', error.message);
    }

    this.profilers.set('memory', {
      samples: memorySamples,
      gcEvents: gcEvents,
      observer: gcObserver,
      stop: () => {
        gcObserver.disconnect();
        console.log(`📊 内存采样完成: ${memorySamples.length} 个样本, ${gcEvents.length} 个GC事件`);
      }
    });
  }

  startFunctionProfiling() {
    const functionCalls = new Map();
    const callStack = [];
    
    // 函数调用跟踪
    const originalConsoleTime = console.time;
    const originalConsoleTimeEnd = console.timeEnd;
    
    console.time = (label) => {
      const startTime = performance.now();
      callStack.push({ label, startTime });
      return originalConsoleTime.call(console, label);
    };
    
    console.timeEnd = (label) => {
      const endTime = performance.now();
      const callIndex = callStack.findIndex(call => call.label === label);
      
      if (callIndex > -1) {
        const call = callStack.splice(callIndex, 1)[0];
        const duration = endTime - call.startTime;
        
        if (!functionCalls.has(label)) {
          functionCalls.set(label, {
            count: 0,
            totalTime: 0,
            minTime: Infinity,
            maxTime: 0,
            calls: []
          });
        }
        
        const stats = functionCalls.get(label);
        stats.count++;
        stats.totalTime += duration;
        stats.minTime = Math.min(stats.minTime, duration);
        stats.maxTime = Math.max(stats.maxTime, duration);
        stats.calls.push({
          timestamp: Date.now(),
          duration: duration
        });
      }
      
      return originalConsoleTimeEnd.call(console, label);
    };

    this.profilers.set('functions', {
      calls: functionCalls,
      stop: () => {
        console.time = originalConsoleTime;
        console.timeEnd = originalConsoleTimeEnd;
        console.log(`📊 函数调用跟踪完成: ${functionCalls.size} 个函数`);
      }
    });
  }

  startCustomMetrics() {
    const customMetrics = {
      httpRequests: 0,
      dbQueries: 0,
      cacheHits: 0,
      cacheMisses: 0,
      errors: 0
    };
    
    // 提供API给应用代码调用
    global.performanceProfiler = {
      incrementMetric: (name, value = 1) => {
        if (customMetrics.hasOwnProperty(name)) {
          customMetrics[name] += value;
        } else {
          customMetrics[name] = value;
        }
      },
      
      recordTiming: (name, duration) => {
        if (!customMetrics.timings) {
          customMetrics.timings = {};
        }
        
        if (!customMetrics.timings[name]) {
          customMetrics.timings[name] = [];
        }
        
        customMetrics.timings[name].push({
          timestamp: Date.now(),
          duration: duration
        });
      }
    };

    this.profilers.set('custom', {
      metrics: customMetrics,
      stop: () => {
        delete global.performanceProfiler;
        console.log('📊 自定义指标收集完成');
      }
    });
  }

  getGCTypeName(kind) {
    const gcTypes = {
      1: 'Scavenge',
      2: 'Mark-Sweep-Compact',
      4: 'Incremental-Marking',
      8: 'Weak-Processing',
      16: 'Full-GC'
    };

    return gcTypes[kind] || `Unknown(${kind})`;
  }

  async generateReports() {
    const timestamp = new Date().toISOString().replace(/[:.]/g, '-');
    const reportDir = path.join(this.options.outputDir, `profile-${timestamp}`);
    
    await fs.mkdir(reportDir, { recursive: true });

    // 生成各种报告
    await this.generateCPUReport(reportDir);
    await this.generateMemoryReport(reportDir);
    await this.generateFunctionReport(reportDir);
    await this.generateCustomMetricsReport(reportDir);
    await this.generateSummaryReport(reportDir);

    if (this.options.enableFlameGraph) {
      await this.generateFlameGraph(reportDir);
    }

    console.log(`📋 性能报告已生成: ${reportDir}`);
  }

  async generateCPUReport(reportDir) {
    const cpuProfiler = this.profilers.get('cpu');
    if (!cpuProfiler) return;

    const samples = cpuProfiler.samples;
    const report = {
      summary: {
        totalSamples: samples.length,
        duration: Date.now() - this.startTime,
        avgUser: samples.reduce((sum, s) => sum + s.user, 0) / samples.length,
        avgSystem: samples.reduce((sum, s) => sum + s.system, 0) / samples.length,
        maxUser: Math.max(...samples.map(s => s.user)),
        maxSystem: Math.max(...samples.map(s => s.system))
      },
      samples: samples
    };

    await fs.writeFile(
      path.join(reportDir, 'cpu-profile.json'),
      JSON.stringify(report, null, 2)
    );

    // 生成CSV格式
    const csvLines = ['timestamp,user,system,total'];
    samples.forEach(sample => {
      csvLines.push(`${sample.timestamp},${sample.user.toFixed(2)},${sample.system.toFixed(2)},${(sample.user + sample.system).toFixed(2)}`);
    });

    await fs.writeFile(
      path.join(reportDir, 'cpu-profile.csv'),
      csvLines.join('\n')
    );
  }

  async generateMemoryReport(reportDir) {
    const memoryProfiler = this.profilers.get('memory');
    if (!memoryProfiler) return;

    const samples = memoryProfiler.samples;
    const gcEvents = memoryProfiler.gcEvents;

    const report = {
      summary: {
        totalSamples: samples.length,
        gcEvents: gcEvents.length,
        peakHeapUsed: Math.max(...samples.map(s => s.heapUsed)),
        peakRSS: Math.max(...samples.map(s => s.rss)),
        avgHeapUtilization: samples.reduce((sum, s) => sum + s.heapUtilization, 0) / samples.length,
        totalGCTime: gcEvents.reduce((sum, gc) => sum + gc.duration, 0)
      },
      memoryTimeline: samples,
      gcTimeline: gcEvents
    };

    await fs.writeFile(
      path.join(reportDir, 'memory-profile.json'),
      JSON.stringify(report, null, 2)
    );

    // 生成内存使用CSV
    const memoryCSV = ['timestamp,heapUsed,heapTotal,rss,external,heapUtilization'];
    samples.forEach(sample => {
      memoryCSV.push(`${sample.timestamp},${sample.heapUsed},${sample.heapTotal},${sample.rss},${sample.external},${sample.heapUtilization.toFixed(2)}`);
    });

    await fs.writeFile(
      path.join(reportDir, 'memory-timeline.csv'),
      memoryCSV.join('\n')
    );

    // 生成GC事件CSV
    const gcCSV = ['timestamp,duration,type,kind'];
    gcEvents.forEach(gc => {
      gcCSV.push(`${gc.timestamp},${gc.duration},${gc.type},${gc.kind}`);
    });

    await fs.writeFile(
      path.join(reportDir, 'gc-events.csv'),
      gcCSV.join('\n')
    );
  }

  async generateFunctionReport(reportDir) {
    const functionProfiler = this.profilers.get('functions');
    if (!functionProfiler) return;

    const functionCalls = functionProfiler.calls;
    const report = {
      summary: {
        totalFunctions: functionCalls.size,
        totalCalls: Array.from(functionCalls.values()).reduce((sum, stats) => sum + stats.count, 0)
      },
      functions: {}
    };

    // 转换为可序列化格式
    for (const [name, stats] of functionCalls) {
      report.functions[name] = {
        count: stats.count,
        totalTime: stats.totalTime,
        avgTime: stats.totalTime / stats.count,
        minTime: stats.minTime,
        maxTime: stats.maxTime,
        calls: stats.calls.slice(-100) // 只保留最近100次调用
      };
    }

    await fs.writeFile(
      path.join(reportDir, 'function-profile.json'),
      JSON.stringify(report, null, 2)
    );

    // 生成函数性能排序CSV
    const sortedFunctions = Array.from(functionCalls.entries())
      .sort(([, a], [, b]) => b.totalTime - a.totalTime);

    const functionCSV = ['function,count,totalTime,avgTime,minTime,maxTime'];
    sortedFunctions.forEach(([name, stats]) => {
      functionCSV.push(`${name},${stats.count},${stats.totalTime.toFixed(2)},${(stats.totalTime / stats.count).toFixed(2)},${stats.minTime.toFixed(2)},${stats.maxTime.toFixed(2)}`);
    });

    await fs.writeFile(
      path.join(reportDir, 'function-performance.csv'),
      functionCSV.join('\n')
    );
  }

  async generateCustomMetricsReport(reportDir) {
    const customProfiler = this.profilers.get('custom');
    if (!customProfiler) return;

    const metrics = customProfiler.metrics;
    
    await fs.writeFile(
      path.join(reportDir, 'custom-metrics.json'),
      JSON.stringify(metrics, null, 2)
    );
  }

  async generateSummaryReport(reportDir) {
    const summary = {
      profilingSession: {
        startTime: this.startTime,
        endTime: Date.now(),
        duration: Date.now() - this.startTime,
        profilers: Array.from(this.profilers.keys())
      },
      recommendations: this.generateRecommendations()
    };

    await fs.writeFile(
      path.join(reportDir, 'summary.json'),
      JSON.stringify(summary, null, 2)
    );

    // 生成HTML报告
    const htmlReport = this.generateHTMLReport(summary);
    await fs.writeFile(
      path.join(reportDir, 'report.html'),
      htmlReport
    );
  }

  generateRecommendations() {
    const recommendations = [];
    
    // CPU建议
    const cpuProfiler = this.profilers.get('cpu');
    if (cpuProfiler) {
      const avgCPU = cpuProfiler.samples.reduce((sum, s) => sum + s.user + s.system, 0) / cpuProfiler.samples.length;
      if (avgCPU > 80) {
        recommendations.push({
          type: 'cpu',
          severity: 'high',
          message: 'CPU使用率过高,考虑优化算法或使用Worker线程'
        });
      }
    }

    // 内存建议
    const memoryProfiler = this.profilers.get('memory');
    if (memoryProfiler) {
      const avgUtilization = memoryProfiler.samples.reduce((sum, s) => sum + s.heapUtilization, 0) / memoryProfiler.samples.length;
      if (avgUtilization > 90) {
        recommendations.push({
          type: 'memory',
          severity: 'high',
          message: '内存利用率过高,检查内存泄漏或增加堆大小'
        });
      }

      const avgGCTime = memoryProfiler.gcEvents.reduce((sum, gc) => sum + gc.duration, 0) / memoryProfiler.gcEvents.length;
      if (avgGCTime > 50) {
        recommendations.push({
          type: 'gc',
          severity: 'medium',
          message: 'GC时间过长,考虑优化对象生命周期'
        });
      }
    }

    return recommendations;
  }

  generateHTMLReport(summary) {
    return `
<!DOCTYPE html>
<html>
<head>
    <title>Node.js 性能分析报告</title>
    <style>
        body { font-family: Arial, sans-serif; margin: 20px; }
        .header { background: #f5f5f5; padding: 20px; border-radius: 5px; }
        .section { margin: 20px 0; padding: 15px; border: 1px solid #ddd; border-radius: 5px; }
        .metric { display: inline-block; margin: 10px; padding: 10px; background: #e9ecef; border-radius: 3px; }
        .recommendation { padding: 10px; margin: 5px 0; border-left: 4px solid #ffc107; background: #fff3cd; }
        .recommendation.high { border-color: #dc3545; background: #f8d7da; }
        .recommendation.medium { border-color: #fd7e14; background: #ffeaa7; }
    </style>
</head>
<body>
    <div class="header">
        <h1>🚀 Node.js 性能分析报告</h1>
        <p>分析时间: ${new Date(summary.profilingSession.startTime).toLocaleString()} - ${new Date(summary.profilingSession.endTime).toLocaleString()}</p>
        <p>持续时间: ${(summary.profilingSession.duration / 1000).toFixed(2)} 秒</p>
        <p>分析器: ${summary.profilingSession.profilers.join(', ')}</p>
    </div>

    <div class="section">
        <h2>📋 优化建议</h2>
        ${summary.recommendations.map(rec => `
            <div class="recommendation ${rec.severity}">
                <strong>${rec.type.toUpperCase()}</strong>: ${rec.message}
            </div>
        `).join('')}
    </div>

    <div class="section">
        <h2>📊 详细报告文件</h2>
        <ul>
            <li><a href="cpu-profile.json">CPU分析报告 (JSON)</a></li>
            <li><a href="memory-profile.json">内存分析报告 (JSON)</a></li>
            <li><a href="function-profile.json">函数调用分析 (JSON)</a></li>
            <li><a href="custom-metrics.json">自定义指标 (JSON)</a></li>
        </ul>
    </div>
</body>
</html>`;
  }

  async generateFlameGraph(reportDir) {
    // 生成火焰图数据(简化版)
    const cpuProfiler = this.profilers.get('cpu');
    if (!cpuProfiler) return;

    const flameData = {
      name: 'root',
      value: cpuProfiler.samples.length,
      children: [
        {
          name: 'user',
          value: Math.floor(cpuProfiler.samples.reduce((sum, s) => sum + s.user, 0))
        },
        {
          name: 'system', 
          value: Math.floor(cpuProfiler.samples.reduce((sum, s) => sum + s.system, 0))
        }
      ]
    };

    await fs.writeFile(
      path.join(reportDir, 'flame-graph.json'),
      JSON.stringify(flameData, null, 2)
    );
  }
}

module.exports = AdvancedPerformanceProfiler;

🔧 第三方性能工具集成

Clinic.js集成

javascript
// clinic-integration.js
const { spawn } = require('child_process');
const path = require('path');
const fs = require('fs').promises;

class ClinicIntegration {
  constructor(options = {}) {
    this.options = {
      outputDir: options.outputDir || './clinic-reports',
      tools: options.tools || ['doctor', 'bubbleprof', 'flame'],
      ...options
    };
  }

  async runDiagnosis(scriptPath, args = []) {
    console.log('🏥 开始Clinic.js诊断...');
    
    const results = {};
    
    for (const tool of this.options.tools) {
      console.log(`🔍 运行 clinic ${tool}...`);
      
      try {
        const result = await this.runClinicTool(tool, scriptPath, args);
        results[tool] = result;
        console.log(`✅ ${tool} 分析完成`);
      } catch (error) {
        console.error(`❌ ${tool} 分析失败:`, error.message);
        results[tool] = { error: error.message };
      }
    }
    
    // 生成综合报告
    await this.generateComprehensiveReport(results);
    
    return results;
  }

  async runClinicTool(tool, scriptPath, args) {
    return new Promise((resolve, reject) => {
      const clinicArgs = [tool, '--dest', this.options.outputDir, scriptPath, ...args];
      const clinic = spawn('clinic', clinicArgs, {
        stdio: 'pipe',
        env: { ...process.env }
      });

      let stdout = '';
      let stderr = '';

      clinic.stdout.on('data', (data) => {
        stdout += data.toString();
      });

      clinic.stderr.on('data', (data) => {
        stderr += data.toString();
      });

      clinic.on('close', (code) => {
        if (code === 0) {
          resolve({
            tool,
            stdout,
            stderr,
            exitCode: code,
            reportPath: this.getReportPath(tool)
          });
        } else {
          reject(new Error(`Clinic ${tool} 退出码: ${code}\n${stderr}`));
        }
      });

      clinic.on('error', (error) => {
        reject(new Error(`启动 clinic ${tool} 失败: ${error.message}`));
      });
    });
  }

  getReportPath(tool) {
    // Clinic.js 生成的报告路径模式
    return path.join(this.options.outputDir, `clinic-${tool}-*.html`);
  }

  async generateComprehensiveReport(results) {
    const reportPath = path.join(this.options.outputDir, 'comprehensive-report.json');
    
    const report = {
      timestamp: new Date().toISOString(),
      tools: results,
      summary: this.generateSummary(results),
      recommendations: this.generateRecommendations(results)
    };

    await fs.writeFile(reportPath, JSON.stringify(report, null, 2));
    console.log(`📋 综合报告已生成: ${reportPath}`);
  }

  generateSummary(results) {
    const summary = {
      toolsRun: Object.keys(results).length,
      successful: Object.values(results).filter(r => !r.error).length,
      failed: Object.values(results).filter(r => r.error).length
    };

    return summary;
  }

  generateRecommendations(results) {
    const recommendations = [];

    // 基于工具结果生成建议
    if (results.doctor && !results.doctor.error) {
      recommendations.push({
        tool: 'doctor',
        message: '查看Doctor报告了解事件循环延迟和CPU使用情况'
      });
    }

    if (results.bubbleprof && !results.bubbleprof.error) {
      recommendations.push({
        tool: 'bubbleprof',
        message: '查看Bubbleprof报告了解异步操作性能'
      });
    }

    if (results.flame && !results.flame.error) {
      recommendations.push({
        tool: 'flame',
        message: '查看火焰图了解CPU热点和函数调用分布'
      });
    }

    return recommendations;
  }
}

// 性能基准测试套件
class PerformanceBenchmarkSuite {
  constructor() {
    this.benchmarks = new Map();
    this.results = [];
  }

  addBenchmark(name, fn, options = {}) {
    this.benchmarks.set(name, {
      fn,
      iterations: options.iterations || 1000,
      warmup: options.warmup || 100,
      timeout: options.timeout || 30000
    });
  }

  async runAll() {
    console.log('🏃 开始性能基准测试套件...\n');
    
    for (const [name, config] of this.benchmarks) {
      console.log(`测试: ${name}`);
      
      try {
        const result = await this.runBenchmark(name, config);
        this.results.push(result);
        
        console.log(`  ✅ 完成: ${result.avgTime.toFixed(4)}ms 平均, ${result.opsPerSecond} ops/sec\n`);
      } catch (error) {
        console.error(`  ❌ 失败: ${error.message}\n`);
        this.results.push({
          name,
          error: error.message,
          success: false
        });
      }
    }

    this.displayResults();
    return this.results;
  }

  async runBenchmark(name, config) {
    const { fn, iterations, warmup, timeout } = config;

    // 预热
    for (let i = 0; i < warmup; i++) {
      await fn();
    }

    const times = [];
    const startTime = Date.now();

    for (let i = 0; i < iterations; i++) {
      const iterStart = process.hrtime.bigint();
      await fn();
      const iterEnd = process.hrtime.bigint();
      
      times.push(Number(iterEnd - iterStart) / 1000000); // 转换为毫秒
      
      // 超时检查
      if (Date.now() - startTime > timeout) {
        throw new Error(`基准测试超时: ${name}`);
      }
    }

    const totalTime = Date.now() - startTime;
    const avgTime = times.reduce((a, b) => a + b, 0) / times.length;
    const minTime = Math.min(...times);
    const maxTime = Math.max(...times);
    
    // 计算标准差
    const variance = times.reduce((acc, time) => acc + Math.pow(time - avgTime, 2), 0) / times.length;
    const stdDev = Math.sqrt(variance);

    return {
      name,
      success: true,
      iterations,
      totalTime,
      avgTime,
      minTime,
      maxTime,
      stdDev,
      opsPerSecond: Math.round(iterations / (totalTime / 1000)),
      times: times.slice(0, 100) // 保留前100个样本
    };
  }

  displayResults() {
    console.log('📊 基准测试结果汇总:');
    console.log('='.repeat(80));
    
    const successful = this.results.filter(r => r.success);
    const failed = this.results.filter(r => !r.success);
    
    if (successful.length > 0) {
      // 按平均时间排序
      successful.sort((a, b) => a.avgTime - b.avgTime);
      
      console.log('\n🏆 成功的测试 (按性能排序):');
      successful.forEach((result, index) => {
        const rank = index + 1;
        const speedup = index === 0 ? '1.00x' : `${(successful[0].avgTime / result.avgTime).toFixed(2)}x`;
        
        console.log(`${rank}. ${result.name}:`);
        console.log(`   平均时间: ${result.avgTime.toFixed(4)}ms`);
        console.log(`   吞吐量: ${result.opsPerSecond} ops/sec`);
        console.log(`   标准差: ${result.stdDev.toFixed(4)}ms`);
        console.log(`   相对速度: ${speedup} ${index === 0 ? '(最快)' : '(相对最快)'}`);
        console.log('');
      });
    }
    
    if (failed.length > 0) {
      console.log('❌ 失败的测试:');
      failed.forEach(result => {
        console.log(`- ${result.name}: ${result.error}`);
      });
    }
    
    console.log(`\n📈 总结: ${successful.length} 成功, ${failed.length} 失败`);
  }

  exportResults(filePath) {
    const report = {
      timestamp: new Date().toISOString(),
      summary: {
        total: this.results.length,
        successful: this.results.filter(r => r.success).length,
        failed: this.results.filter(r => !r.success).length
      },
      results: this.results
    };

    require('fs').writeFileSync(filePath, JSON.stringify(report, null, 2));
    console.log(`📄 结果已导出到: ${filePath}`);
  }
}

module.exports = {
  ClinicIntegration,
  PerformanceBenchmarkSuite
};

Node.js性能分析工具为开发者提供了强大的性能诊断能力,通过合理使用这些工具可以快速定位和解决性能问题!