第17章 - 性能优化与最佳实践

第17章:性能优化与最佳实践

17.1 性能优化原则

17.1.1 性能瓶颈分析

// 启用性能监控
viewer.scene.debugShowFramesPerSecond = true;

// 扩展 3D Tiles Inspector
viewer.extend(Cesium.viewerCesium3DTilesInspectorMixin);

// 内存监控
setInterval(() => {
    if (performance.memory) {
        console.log('内存使用:', {
            usedJSHeapSize: (performance.memory.usedJSHeapSize / 1024 / 1024).toFixed(2) + ' MB',
            totalJSHeapSize: (performance.memory.totalJSHeapSize / 1024 / 1024).toFixed(2) + ' MB'
        });
    }
}, 5000);

17.2 渲染优化

17.2.1 按需渲染

// 启用按需渲染模式
viewer.scene.requestRenderMode = true;
viewer.scene.maximumRenderTimeChange = Infinity;

// 手动请求渲染
function requestRender() {
    viewer.scene.requestRender();
}

// 数据变化时请求渲染
viewer.entities.collectionChanged.addEventListener(requestRender);

17.2.2 Primitive vs Entity

// Entity(简单但性能较低)
// 适合:< 1000 个对象,需要拾取,需要动态属性
viewer.entities.add({
    position: Cesium.Cartesian3.fromDegrees(lon, lat),
    point: { pixelSize: 10 }
});

// Primitive(性能更高)
// 适合:> 1000 个对象,静态数据
const pointCollection = new Cesium.PointPrimitiveCollection();
for (let i = 0; i < 100000; i++) {
    pointCollection.add({
        position: Cesium.Cartesian3.fromDegrees(
            100 + Math.random() * 30,
            20 + Math.random() * 20
        ),
        pixelSize: 5,
        color: Cesium.Color.RED
    });
}
viewer.scene.primitives.add(pointCollection);

17.2.3 批量操作

// 挂起事件进行批量操作
const entities = viewer.entities;
entities.suspendEvents();

try {
    for (let i = 0; i < 10000; i++) {
        entities.add({
            position: Cesium.Cartesian3.fromDegrees(lon, lat),
            point: { pixelSize: 5 }
        });
    }
} finally {
    entities.resumeEvents();
}

17.3 数据优化

17.3.1 3D Tiles 优化

const tileset = await Cesium.Cesium3DTileset.fromUrl(url, {
    // LOD 优化
    maximumScreenSpaceError: 16,        // 增大可降低精度提高性能
    maximumMemoryUsage: 512,            // 限制内存
    
    // 跳级加载
    skipLevelOfDetail: true,
    skipLevels: 1,
    
    // 剔除优化
    cullWithChildrenBounds: true,
    cullRequestsWhileMoving: true,
    cullRequestsWhileMovingMultiplier: 60.0,
    
    // 预加载
    preloadWhenHidden: false,
    preloadFlightDestinations: true,
    preferLeaves: false
});

// 动态调整(根据帧率)
let lastFPS = 60;
viewer.scene.postRender.addEventListener(() => {
    const fps = viewer.scene.debugShowFramesPerSecond ? 
        parseFloat(document.querySelector('.cesium-performanceDisplay-fps').textContent) : 60;
    
    if (fps < 30 && tileset.maximumScreenSpaceError < 64) {
        tileset.maximumScreenSpaceError *= 1.1;
    } else if (fps > 55 && tileset.maximumScreenSpaceError > 4) {
        tileset.maximumScreenSpaceError *= 0.95;
    }
});

17.3.2 影像优化

// 限制瓦片缓存
viewer.scene.globe.tileCacheSize = 100;

// 限制最大请求数
Cesium.RequestScheduler.maximumRequestsPerServer = 6;

// 减少影像图层数
// 移除不需要的图层
viewer.imageryLayers.removeAll();
viewer.imageryLayers.addImageryProvider(primaryImagery);

17.3.3 地形优化

// 降低地形精度
viewer.scene.globe.maximumScreenSpaceError = 4;

// 禁用地形(如果不需要)
viewer.terrainProvider = new Cesium.EllipsoidTerrainProvider();

// 限制地形级别
viewer.scene.globe.loadingDescendantLimit = 20;

17.4 内存管理

// 及时销毁不用的资源
function cleanupResources() {
    // 清除实体
    viewer.entities.removeAll();
    
    // 清除数据源
    viewer.dataSources.removeAll(true);
    
    // 清除图元
    viewer.scene.primitives.removeAll();
    
    // 清除地面图元
    viewer.scene.groundPrimitives.removeAll();
}

// 销毁 Viewer
function destroyViewer() {
    if (viewer && !viewer.isDestroyed()) {
        viewer.destroy();
    }
}

17.5 最佳实践

17.5.1 项目结构

cesium-project/
├── src/
│   ├── main.js
│   ├── config/          # 配置文件
│   ├── components/      # 组件
│   ├── layers/          # 图层管理
│   ├── tools/           # 工具类
│   └── utils/           # 工具函数
├── public/
│   ├── assets/          # 静态资源
│   │   ├── models/      # 3D模型
│   │   └── textures/    # 纹理
│   └── data/            # 数据文件
└── package.json

17.5.2 代码规范

// 使用异步/等待
async function loadData() {
    try {
        const tileset = await Cesium.Cesium3DTileset.fromUrl(url);
        viewer.scene.primitives.add(tileset);
        await viewer.zoomTo(tileset);
    } catch (error) {
        console.error('加载失败:', error);
    }
}

// 清理事件监听
class MyComponent {
    constructor(viewer) {
        this.viewer = viewer;
        this.handler = new Cesium.ScreenSpaceEventHandler(viewer.canvas);
        this.removeCallbacks = [];
    }
    
    init() {
        // 保存回调以便清理
        const callback = (e) => this.onClick(e);
        this.handler.setInputAction(callback, Cesium.ScreenSpaceEventType.LEFT_CLICK);
    }
    
    destroy() {
        if (this.handler) {
            this.handler.destroy();
            this.handler = null;
        }
    }
}

17.5.3 错误处理

// 全局错误处理
window.onerror = function(message, source, lineno, colno, error) {
    console.error('全局错误:', { message, source, lineno, colno, error });
    return false;
};

// Promise 错误处理
window.onunhandledrejection = function(event) {
    console.error('未处理的 Promise 错误:', event.reason);
};

// CesiumJS 错误处理
viewer.scene.renderError.addEventListener(function(scene, error) {
    console.error('渲染错误:', error);
});

17.6 本章小结

本章介绍了性能优化与最佳实践:

  1. 性能监控:帧率、内存监控
  2. 渲染优化:按需渲染、Primitive
  3. 数据优化:3D Tiles、影像、地形
  4. 内存管理:资源清理、销毁
  5. 最佳实践:项目结构、代码规范

在下一章中,我们将通过实战案例综合应用所学内容。

17.7 思考与练习

  1. 对现有项目进行性能分析。
  2. 优化大规模数据加载。
  3. 实现自适应 LOD 调整。
  4. 开发性能监控面板。
  5. 优化移动端体验。
posted @ 2026-01-08 11:13  我才是银古  阅读(11)  评论(0)    收藏  举报