Cesium | 海量点的加载与性能优化

前言

在Cesium中我们可能会遇到加载海量数据的情况,但当我们进行实现的时候会发现页面渲染会因为数据量过大而变得迟缓,十分影响用户体验。接下来我将先通过大数量的点进行性能检测,然后对其进行优化。

本文利用Turf进行海量随机点的生成

测试

首先我们通过Turf生成万量级的点位信息

1
2
3
4
5
6
7
8
9
10
11
12
13
14
let points = turf.randomPoint(10000, { bbox: [40, 20, 255, 60] });
let features = points.features;
let feature, geom, coordinates, position;

for (let i = 0; i < features.length; i++) {
feature = features[i];
geom = feature.geometry;
coordinates = geom.coordinates;
position = Cesium.Cartesian3.fromDegrees(
coordinates[0],
coordinates[1],
0
);
this.addEntities(position);

addEntities方法中进行我们的billboard添加

1
2
3
4
5
6
7
viewer.entities.add({
position: position,
billboard: {
image: "./static/blueCamera.png",
verticalOrigin: Cesium.VerticalOrigin.BOTTOM,
},
});

然后我们打开我们的项目……天啊真是肉眼可见的卡住了,接下来我们用performance来分析一下。

image-20210607164830355.png

我们点击左上角的刷新按钮,reload一下页面,等待分析报告的生成。

image-20210609141301351.png

可以看到我们万级别的billboard在以entity为载体的情况下添加花费了近30s的时间非常之长。

我们上述是通过加载本地图片资源,然后给Cesium生成对应的billboard去利用entity进行渲染,慢会不会是因为通过entity生成的原因?,如果我们用primitive呢,这里简单讲一下primitveentity的区别,详细的描述后续会单独写一篇文章作述。

primitiveentity

  • primitive更多的是面向图形开发人员的底层API,暴露最小限度的抽象,更多使用图形学术语,具有更大的灵活性。
  • entity是更高级别的数据驱动API,它使用一致性设计的、高级别对象来管理一组相关性的可视化对象,其底层也是使用的primitive

primitive利用GeometryAppearance构建,其具有以下优势:

  1. 性能:绘制大量Primitive时,可以将其合并为单个Geometry,减轻CPU负担,更好使用GPU。
  2. 灵活:GeometryAppearance解耦,两者可独立修改。

同样的,使用primitive就意味着需要编写更多代码,以及对图形学深入的了解。

优化

Cesium内部为我们提供了几个可渲染的集合像PointPrimitiveCollectionBillboardCollection等等,这里我们就可以用到BillboardCollection,官方API是这样讲关于它的性能的(自己根据理解翻译的可能有错,所以这里把原文也放上吧):

Performance:

For best performance, prefer a few collections, each with many billboards, to many collections with only a few billboards each. Organize collections so that billboards with the same update frequency are in the same collection, i.e., billboards that do not change should be in one collection; billboards that change every frame should be in another collection; and so on.

为了获得最佳性能,最好使用更少的内部拥有更多billboard的集合,而不是每个集合里只有零星的billboard,而对于集合的组织上,让拥有同样更新频率(即不会变化)的billboard存在于一个集合中,而把每一帧都变化的billboard放到另一个集合当中。

接下来我们使用BillboardCollection生成10000个点并利用控制台分析一下性能。

1
2
3
4
5
6
7
8
9
10
11
12
13
this.billboards = viewer.scene.primitives.add(
new Cesium.BillboardCollection()
);
// ...

addPrimitive(position) {
this.billboards.add({
position: position,
image: require("./images/blueCamera.png"),
verticalOrigin: Cesium.VerticalOrigin.BOTTOM,
});
},

image-20210609162506922.png

可以看到生成速度提高了许多。

既然这样那我们再测试一下十万量级的点的加载速度:

image-20210609162137395.png
两者竟然不分上下,可见primitive有多么强大。

最后

后续其实我们可以进行更深层的优化,比如图片我们现在是从本地获取的,能不能将它存到数据库或者浏览器中快速取出节省时间等等。像我们如果做地级市的系统,那房屋、道路这些要素都是至少万以上量级,这些又该怎么优化,如何保证用户体验等等。Echart都可以实现千万级别量级的点展示,说明性能优化这里的水很深啊哈哈。


Cesium | 海量点的加载与性能优化
https://moewang0321.github.io/2021/06/11/Cesium海量点的加载与性能优化/
作者
Moe Wang
发布于
2021年6月11日
许可协议