1. 渲染性能分析工具

我来详细介绍 Three.js 渲染性能分析工具,帮助你诊断和优化性能问题。

Three.js 内置工具

1.1. Stats.js

最常用的性能监控工具:

import Stats from 'three/addons/libs/stats.module.js';

const stats = new Stats();
stats.showPanel(0); // 0: fps, 1: ms, 2: mb, 3+: custom
document.body.appendChild(stats.dom);

function animate() {
  stats.begin();
  // 渲染场景
  renderer.render(scene, camera);
  stats.end();
  requestAnimationFrame(animate);
}

1.2. WebGLRenderer.info

内置的性能统计信息:

console.log(renderer.info);
// 输出:
// {
//   memory: { geometries: 10, textures: 5 },
//   render: { calls: 100, triangles: 50000, points: 0, lines: 0 },
//   programs: 8
// }

浏览器开发者工具

1.3. Performance 面板

  1. 录制性能数据
  2. 分析调用堆栈
  3. 查看 GPU 使用情况
  4. 检测内存泄漏

1.4. Memory 面板

监控内存使用情况,检测 Three.js 对象泄漏。

专用 Three.js 性能分析工具

1.5. three-mesh-bvh 性能分析

import { computeBoundsTree, disposeBoundsTree } from 'three-mesh-bvh';

// 启用BVH性能统计
const geometry = new THREE.BoxGeometry();
geometry.boundsTree = computeBoundsTree(geometry);
console.log(geometry.boundsTree.stats);

1.6. threejs-inspector

浏览器扩展,可视化检查 Three.js 场景:

GPU 性能分析

1.7. WebGL 调试工具

// 启用WebGL调试
const renderer = new THREE.WebGLRenderer({
  powerPreference: "high-performance",
  antialias: false,
  stencil: false,
  depth: false
});

// 检查扩展
console.log(renderer.capabilities);

1.8. GPU.js 分析

// 监控GPU帧时间
const query = renderer.getContext().createQuery();
renderer.getContext().beginQuery(renderer.getContext().TIME_ELAPSED_EXT, query);
// 渲染代码...
renderer.getContext().endQuery(renderer.getContext().TIME_ELAPSED_EXT);

自定义性能监控

1.9. 帧时间分析

class PerformanceMonitor {
  constructor() {
    this.frameTimes = [];
    this.maxSamples = 60;
  }

  beginFrame() {
    this.startTime = performance.now();
  }

  endFrame() {
    const frameTime = performance.now() - this.startTime;
    this.frameTimes.push(frameTime);

    if (this.frameTimes.length > this.maxSamples) {
      this.frameTimes.shift();
    }

    const avg = this.frameTimes.reduce((a, b) => a + b) / this.frameTimes.length;
    console.log(`平均帧时间: ${avg.toFixed(2)}ms (${(1000/avg).toFixed(1)} FPS)`);
  }
}

1.10. 对象计数监控

class ObjectCounter {
  constructor() {
    this.counts = {
      meshes: 0,
      vertices: 0,
      triangles: 0,
      textures: 0,
      materials: 0
    };
  }

  analyzeScene(scene) {
    scene.traverse((object) => {
      if (object.isMesh) {
        this.counts.meshes++;
        const geometry = object.geometry;
        if (geometry) {
          this.counts.vertices += geometry.attributes.position.count;
          this.counts.triangles += geometry.index ? geometry.index.count / 3 : geometry.attributes.position.count / 3;
        }
      }
      if (object.material) {
        this.counts.materials++;
      }
    });

    return this.counts;
  }
}

性能优化检测工具

1.11. 检测常见问题

class PerformanceChecker {
  static checkIssues(renderer, scene) {
    const issues = [];

    // 检查draw calls
    if (renderer.info.render.calls > 1000) {
      issues.push(`Draw calls过高: ${renderer.info.render.calls}`);
    }

    // 检查三角形数量
    if (renderer.info.render.triangles > 1000000) {
      issues.push(`三角形数量过多: ${renderer.info.render.triangles}`);
    }

    // 检查纹理内存
    if (renderer.info.memory.textures > 50) {
      issues.push(`纹理数量过多: ${renderer.info.memory.textures}`);
    }

    return issues;
  }
}

实用分析脚本

1.12. 完整性能仪表板

class PerformanceDashboard {
  constructor(renderer, scene) {
    this.renderer = renderer;
    this.scene = scene;
    this.stats = new Stats();
    this.setupUI();
  }

  setupUI() {
    // 创建控制面板
    this.panel = document.createElement('div');
    this.panel.style.cssText = `
      position: fixed; top: 10px; right: 10px;
      background: rgba(0,0,0,0.8); color: white;
      padding: 10px; font-family: monospace;
      z-index: 10000;
    `;
    document.body.appendChild(this.panel);

    // 添加Stats.js
    this.stats.dom.style.position = 'relative';
    this.stats.dom.style.top = '0';
    this.panel.appendChild(this.stats.dom);
  }

  update() {
    const info = this.renderer.info;
    const statsHTML = `
      <div style="margin-top: 10px;">
        <div>Draw Calls: ${info.render.calls}</div>
        <div>Triangles: ${info.render.triangles.toLocaleString()}</div>
        <div>Textures: ${info.memory.textures}</div>
        <div>Geometries: ${info.memory.geometries}</div>
        <div>Shaders: ${info.programs ? info.programs.length : 0}</div>
      </div>
    `;

    // 更新显示
    const existingStats = this.panel.querySelector('.custom-stats');
    if (existingStats) {
      existingStats.innerHTML = statsHTML;
    } else {
      const div = document.createElement('div');
      div.className = 'custom-stats';
      div.innerHTML = statsHTML;
      this.panel.appendChild(div);
    }
  }
}

最佳实践建议

1.13. 监控策略

  1. 开发阶段:始终开启 Stats.js
  2. 性能测试:使用 Chrome Performance 录制
  3. 内存检查:定期使用 Memory 面板快照
  4. 生产环境:实现轻量级性能上报

1.14. 关键指标阈值

1.15. 自动化测试

// 性能回归测试
function runPerformanceTest(scene, camera, renderer, duration = 5000) {
  const startTime = Date.now();
  const frameTimes = [];

  function frame() {
    const start = performance.now();
    renderer.render(scene, camera);
    const end = performance.now();
    frameTimes.push(end - start);

    if (Date.now() - startTime < duration) {
      requestAnimationFrame(frame);
    } else {
      analyzeResults(frameTimes);
    }
  }

  frame();
}

这些工具和技巧能帮助你全面分析 Three.js 应用的渲染性能,快速定位瓶颈并进行优化。