Skip to content

性能分析

robuild 的性能分析系统帮助你了解构建性能,识别瓶颈,并优化构建过程。

性能监控架构

整体设计

mermaid
graph TB
    A[构建引擎] --> B[性能监控器]
    B --> C[时间追踪]
    B --> D[内存监控]
    B --> E[资源分析]

    C --> F[阶段计时]
    C --> G[操作计时]

    D --> H[内存使用]
    D --> I[垃圾回收]

    E --> J[文件大小]
    E --> K[依赖分析]

    subgraph "性能报告"
        L[控制台输出]
        M[JSON 报告]
        N[可视化图表]
    end

    B --> L
    B --> M
    B --> N

性能监控器

核心实现

typescript
// src/performance/monitor.ts
export class PerformanceMonitor {
  private timers: Map<string, Timer> = new Map()
  private memorySnapshots: MemorySnapshot[] = []
  private metrics: BuildMetrics = {
    totalTime: 0,
    phases: {},
    memory: {
      peak: 0,
      average: 0,
      gc: 0
    },
    files: {
      processed: 0,
      totalSize: 0,
      averageSize: 0
    }
  }

  constructor(private options: MonitorOptions = {}) {
    this.startTime = Date.now()
  }

  // 开始计时
  startTimer(name: string): void {
    this.timers.set(name, {
      start: Date.now(),
      end: 0,
      duration: 0
    })
  }

  // 结束计时
  endTimer(name: string): number {
    const timer = this.timers.get(name)
    if (!timer) {
      throw new Error(`计时器不存在: ${name}`)
    }

    timer.end = Date.now()
    timer.duration = timer.end - timer.start

    this.metrics.phases[name] = timer.duration
    return timer.duration
  }

  // 记录内存快照
  takeMemorySnapshot(): void {
    const usage = process.memoryUsage()
    this.memorySnapshots.push({
      timestamp: Date.now(),
      rss: usage.rss,
      heapUsed: usage.heapUsed,
      heapTotal: usage.heapTotal,
      external: usage.external
    })

    // 更新峰值内存
    this.metrics.memory.peak = Math.max(
      this.metrics.memory.peak,
      usage.heapUsed
    )
  }

  // 生成报告
  generateReport(): PerformanceReport {
    this.calculateMetrics()

    return {
      summary: this.generateSummary(),
      details: this.generateDetails(),
      recommendations: this.generateRecommendations()
    }
  }
}

计时器系统

typescript
interface Timer {
  start: number
  end: number
  duration: number
}

interface BuildMetrics {
  totalTime: number
  phases: Record<string, number>
  memory: {
    peak: number
    average: number
    gc: number
  }
  files: {
    processed: number
    totalSize: number
    averageSize: number
  }
}

性能追踪

1. 构建阶段追踪

typescript
// src/performance/tracker.ts
export class BuildTracker {
  constructor(private monitor: PerformanceMonitor) {}

  // 追踪配置加载
  async trackConfigLoad<T>(fn: () => Promise<T>): Promise<T> {
    this.monitor.startTimer('config-load')
    try {
      const result = await fn()
      return result
    } finally {
      this.monitor.endTimer('config-load')
    }
  }

  // 追踪文件扫描
  async trackFileScan<T>(fn: () => Promise<T>): Promise<T> {
    this.monitor.startTimer('file-scan')
    try {
      const result = await fn()
      return result
    } finally {
      this.monitor.endTimer('file-scan')
    }
  }

  // 追踪构建过程
  async trackBuild<T>(entry: BuildEntry, fn: () => Promise<T>): Promise<T> {
    const phaseName = `build-${entry.type}-${basename(entry.input)}`
    this.monitor.startTimer(phaseName)

    try {
      const result = await fn()
      return result
    } finally {
      this.monitor.endTimer(phaseName)
    }
  }

  // 追踪后处理
  async trackPostProcess<T>(fn: () => Promise<T>): Promise<T> {
    this.monitor.startTimer('post-process')
    try {
      const result = await fn()
      return result
    } finally {
      this.monitor.endTimer('post-process')
    }
  }
}

2. 内存监控

typescript
// src/performance/memory.ts
export class MemoryMonitor {
  private snapshots: MemorySnapshot[] = []
  private gcCount = 0

  constructor(private monitor: PerformanceMonitor) {
    this.setupGCMonitoring()
  }

  // 设置 GC 监控
  private setupGCMonitoring(): void {
    if (typeof gc === 'function') {
      const originalGC = gc
      gc = () => {
        this.gcCount++
        originalGC()
      }
    }
  }

  // 定期快照
  startPeriodicSnapshots(interval: number = 1000): void {
    setInterval(() => {
      this.takeSnapshot()
    }, interval)
  }

  // 获取内存快照
  private takeSnapshot(): void {
    const usage = process.memoryUsage()
    this.snapshots.push({
      timestamp: Date.now(),
      rss: usage.rss,
      heapUsed: usage.heapUsed,
      heapTotal: usage.heapTotal,
      external: usage.external
    })
  }

  // 分析内存使用
  analyzeMemoryUsage(): MemoryAnalysis {
    if (this.snapshots.length === 0) {
      return { average: 0, peak: 0, trend: 'stable' }
    }

    const heapUsed = this.snapshots.map(s => s.heapUsed)
    const average = heapUsed.reduce((a, b) => a + b, 0) / heapUsed.length
    const peak = Math.max(...heapUsed)

    // 分析趋势
    const trend = this.analyzeTrend(heapUsed)

    return { average, peak, trend }
  }

  // 分析内存趋势
  private analyzeTrend(values: number[]): 'increasing' | 'decreasing' | 'stable' {
    if (values.length < 2) return 'stable'

    const firstHalf = values.slice(0, Math.floor(values.length / 2))
    const secondHalf = values.slice(Math.floor(values.length / 2))

    const firstAvg = firstHalf.reduce((a, b) => a + b, 0) / firstHalf.length
    const secondAvg = secondHalf.reduce((a, b) => a + b, 0) / secondHalf.length

    const diff = secondAvg - firstAvg
    const threshold = firstAvg * 0.1 // 10% 阈值

    if (diff > threshold) return 'increasing'
    if (diff < -threshold) return 'decreasing'
    return 'stable'
  }
}

3. 文件分析

typescript
// src/performance/file-analyzer.ts
export class FileAnalyzer {
  private fileStats: Map<string, FileStats> = new Map()

  // 分析文件
  analyzeFile(filePath: string, content: string): FileStats {
    const stats = {
      path: filePath,
      size: content.length,
      lines: content.split('\n').length,
      imports: this.countImports(content),
      exports: this.countExports(content),
      complexity: this.calculateComplexity(content)
    }

    this.fileStats.set(filePath, stats)
    return stats
  }

  // 统计导入
  private countImports(content: string): number {
    const importRegex = /^import\s+/gm
    return (content.match(importRegex) || []).length
  }

  // 统计导出
  private countExports(content: string): number {
    const exportRegex = /^export\s+/gm
    return (content.match(exportRegex) || []).length
  }

  // 计算复杂度
  private calculateComplexity(content: string): number {
    let complexity = 0

    // 循环复杂度
    const loops = content.match(/\b(for|while|do)\b/g) || []
    complexity += loops.length

    // 条件复杂度
    const conditions = content.match(/\b(if|else|switch|case)\b/g) || []
    complexity += conditions.length

    // 函数复杂度
    const functions = content.match(/\b(function|=>)\b/g) || []
    complexity += functions.length

    return complexity
  }

  // 生成文件报告
  generateFileReport(): FileReport {
    const files = Array.from(this.fileStats.values())

    return {
      totalFiles: files.length,
      totalSize: files.reduce((sum, f) => sum + f.size, 0),
      averageSize: files.reduce((sum, f) => sum + f.size, 0) / files.length,
      largestFile: files.reduce((max, f) => f.size > max.size ? f : max),
      mostComplexFile: files.reduce((max, f) => f.complexity > max.complexity ? f : max),
      fileTypes: this.analyzeFileTypes(files)
    }
  }

  // 分析文件类型
  private analyzeFileTypes(files: FileStats[]): Record<string, number> {
    const types: Record<string, number> = {}

    for (const file of files) {
      const ext = extname(file.path)
      types[ext] = (types[ext] || 0) + 1
    }

    return types
  }
}

性能报告

1. 报告生成器

typescript
// src/performance/reporter.ts
export class PerformanceReporter {
  constructor(private monitor: PerformanceMonitor) {}

  // 生成控制台报告
  generateConsoleReport(): void {
    const report = this.monitor.generateReport()

    console.log('\n📊 构建性能报告')
    console.log('=' * 50)

    // 总体统计
    console.log(`总构建时间: ${report.summary.totalTime}ms`)
    console.log(`峰值内存: ${this.formatBytes(report.summary.peakMemory)}`)
    console.log(`处理文件: ${report.summary.filesProcessed}`)

    // 阶段分析
    console.log('\n阶段分析:')
    for (const [phase, duration] of Object.entries(report.details.phases)) {
      const percentage = ((duration / report.summary.totalTime) * 100).toFixed(1)
      console.log(`  ${phase}: ${duration}ms (${percentage}%)`)
    }

    // 性能建议
    if (report.recommendations.length > 0) {
      console.log('\n性能建议:')
      report.recommendations.forEach((rec, index) => {
        console.log(`  ${index + 1}. ${rec}`)
      })
    }
  }

  // 生成 JSON 报告
  generateJsonReport(): string {
    const report = this.monitor.generateReport()
    return JSON.stringify(report, null, 2)
  }

  // 生成 HTML 报告
  generateHtmlReport(): string {
    const report = this.monitor.generateReport()
    return this.renderHtmlTemplate(report)
  }

  // 格式化字节
  private formatBytes(bytes: number): string {
    const units = ['B', 'KB', 'MB', 'GB']
    let size = bytes
    let unitIndex = 0

    while (size >= 1024 && unitIndex < units.length - 1) {
      size /= 1024
      unitIndex++
    }

    return `${size.toFixed(2)} ${units[unitIndex]}`
  }
}

2. 报告模板

typescript
interface PerformanceReport {
  summary: {
    totalTime: number
    peakMemory: number
    filesProcessed: number
  }
  details: {
    phases: Record<string, number>
    memory: MemoryAnalysis
    files: FileReport
  }
  recommendations: string[]
}

性能优化建议

1. 自动建议生成

typescript
// src/performance/advisor.ts
export class PerformanceAdvisor {
  // 生成优化建议
  generateRecommendations(metrics: BuildMetrics): string[] {
    const recommendations: string[] = []

    // 分析构建时间
    this.analyzeBuildTime(metrics, recommendations)

    // 分析内存使用
    this.analyzeMemoryUsage(metrics, recommendations)

    // 分析文件处理
    this.analyzeFileProcessing(metrics, recommendations)

    return recommendations
  }

  // 分析构建时间
  private analyzeBuildTime(metrics: BuildMetrics, recommendations: string[]): void {
    const slowPhases = Object.entries(metrics.phases)
      .filter(([_, duration]) => duration > 1000)
      .sort(([_, a], [__, b]) => b - a)

    if (slowPhases.length > 0) {
      const [phase, duration] = slowPhases[0]
      recommendations.push(
        `${phase} 阶段耗时 ${duration}ms,考虑优化该阶段的处理逻辑`
      )
    }

    if (metrics.totalTime > 10000) {
      recommendations.push('总构建时间较长,考虑启用缓存或并行处理')
    }
  }

  // 分析内存使用
  private analyzeMemoryUsage(metrics: BuildMetrics, recommendations: string[]): void {
    const peakMB = metrics.memory.peak / 1024 / 1024

    if (peakMB > 500) {
      recommendations.push('内存使用峰值较高,考虑优化内存密集型操作')
    }

    if (metrics.memory.gc > 10) {
      recommendations.push('垃圾回收频繁,考虑减少内存分配或优化数据结构')
    }
  }

  // 分析文件处理
  private analyzeFileProcessing(metrics: BuildMetrics, recommendations: string[]): void {
    if (metrics.files.processed > 100) {
      recommendations.push('处理文件较多,考虑使用增量构建或文件过滤')
    }

    const avgSizeKB = metrics.files.averageSize / 1024
    if (avgSizeKB > 100) {
      recommendations.push('文件平均大小较大,考虑代码分割或懒加载')
    }
  }
}

性能基准测试

1. 基准测试框架

typescript
// src/performance/benchmark.ts
export class BenchmarkRunner {
  private results: BenchmarkResult[] = []

  // 运行基准测试
  async runBenchmark(
    name: string,
    fn: () => Promise<any>,
    iterations: number = 5
  ): Promise<BenchmarkResult> {
    const times: number[] = []
    const memorySnapshots: MemorySnapshot[] = []

    console.log(`运行基准测试: ${name}`)

    for (let i = 0; i < iterations; i++) {
      // 清理内存
      if (typeof gc === 'function') {
        gc()
      }

      // 记录开始状态
      const startMemory = process.memoryUsage()
      const startTime = Date.now()

      // 执行测试
      await fn()

      // 记录结束状态
      const endTime = Date.now()
      const endMemory = process.memoryUsage()

      times.push(endTime - startTime)
      memorySnapshots.push({
        timestamp: endTime,
        rss: endMemory.rss - startMemory.rss,
        heapUsed: endMemory.heapUsed - startMemory.heapUsed,
        heapTotal: endMemory.heapTotal - startMemory.heapTotal,
        external: endMemory.external - startMemory.external
      })
    }

    const result: BenchmarkResult = {
      name,
      iterations,
      times,
      memorySnapshots,
      averageTime: times.reduce((a, b) => a + b, 0) / times.length,
      minTime: Math.min(...times),
      maxTime: Math.max(...times),
      averageMemory: memorySnapshots.reduce((sum, s) => sum + s.heapUsed, 0) / memorySnapshots.length
    }

    this.results.push(result)
    return result
  }

  // 生成基准测试报告
  generateBenchmarkReport(): BenchmarkReport {
    return {
      summary: this.generateSummary(),
      results: this.results,
      comparisons: this.generateComparisons()
    }
  }

  // 生成比较报告
  private generateComparisons(): BenchmarkComparison[] {
    const comparisons: BenchmarkComparison[] = []

    for (let i = 0; i < this.results.length; i++) {
      for (let j = i + 1; j < this.results.length; j++) {
        const a = this.results[i]
        const b = this.results[j]

        const timeDiff = ((b.averageTime - a.averageTime) / a.averageTime) * 100
        const memoryDiff = ((b.averageMemory - a.averageMemory) / a.averageMemory) * 100

        comparisons.push({
          testA: a.name,
          testB: b.name,
          timeDifference: timeDiff,
          memoryDifference: memoryDiff,
          faster: timeDiff > 0 ? a.name : b.name,
          moreEfficient: memoryDiff > 0 ? a.name : b.name
        })
      }
    }

    return comparisons
  }
}

2. 基准测试示例

typescript
// 运行基准测试
const benchmark = new BenchmarkRunner()

// 测试不同构建模式
await benchmark.runBenchmark('Bundle Mode', async () => {
  await buildWithBundleMode()
})

await benchmark.runBenchmark('Transform Mode', async () => {
  await buildWithTransformMode()
})

// 生成报告
const report = benchmark.generateBenchmarkReport()
console.log(JSON.stringify(report, null, 2))

性能监控集成

1. 构建引擎集成

typescript
// src/build.ts
export class BuildEngine {
  private performanceMonitor: PerformanceMonitor
  private tracker: BuildTracker

  constructor(options: BuildOptions) {
    this.performanceMonitor = new PerformanceMonitor(options.performance)
    this.tracker = new BuildTracker(this.performanceMonitor)
  }

  async build(config: BuildConfig): Promise<BuildResult> {
    // 开始性能监控
    this.performanceMonitor.startTimer('total-build')

    try {
      // 追踪各个阶段
      const resolvedConfig = await this.tracker.trackConfigLoad(() =>
        this.resolveConfig(config)
      )

      const results = await this.tracker.trackBuild(resolvedConfig, () =>
        this.executeBuild(resolvedConfig)
      )

      const finalResult = await this.tracker.trackPostProcess(() =>
        this.postProcess(results)
      )

      return finalResult
    } finally {
      // 结束性能监控
      this.performanceMonitor.endTimer('total-build')

      // 生成性能报告
      if (this.options.performance?.report) {
        const reporter = new PerformanceReporter(this.performanceMonitor)
        reporter.generateConsoleReport()
      }
    }
  }
}

2. 配置选项

typescript
interface PerformanceOptions {
  enabled?: boolean
  report?: boolean
  detailed?: boolean
  output?: 'console' | 'json' | 'html'
  file?: string
}

下一步

Released under the MIT License.