Cesium内存消耗问题

标签: Cesium 分类: Gis 创建时间:2023-03-30 02:22:25 更新时间:2023-10-20 11:23:25

前言

我用Mars3d开发的时候,加载了一个官方提供的石化工厂的3dtiles模型,在官方在线例子中,查看的时候,无论如何都不会出现内存占用过大的问题,但是在我本地开发的时候,却出现了在谷歌浏览器中加载这个模型,内存占用率就超过了6.5G,导致电脑一直都在疯狂的转圈,甚至导致系统卡顿了。于是我尝试使用了多种方式进行问题的排查,希望能找出问题的根本原因。这个问题让我很头大,就是我使用了官方提供的一个vue3版本的模版,我什么都没有做,只是加载了一个3dtiles模型,内存竟然表甥到了6G,我分别尝试了使用官方在线例子,官方的Vue版本,和官方的es5版本分别的内存占用,打开相关链接之后,什么都不动的情况下,在一到两分钟之后,结果只有官方在线例子不会出现问题,其他的都会达到6G的内存占用。

【问题】
1.3dtiles总共大小为80M。
2.Mars3D在线版内存占用低,只有几百M。
3.Mars3D开发版(Vue、ES),以及原生的Cesium内存占用都非常的高,达到了6.5G。

【尝试】
(1) 使用官方提供的Vue3的模版,然后用 mars3d.layer.TilesetLayer 加载石化模型,出现内存达到6.5G。
(1) 使用官方提供的Vue3的模版,使用原生的Cesium进行模型的加载,同样会出现这个问题。
(2) 将模型下载到本地进行加载,修改上述地址,同样出现内存占用过大问题,下载到本地的3dtiles总共的文件只有80M。
(3) 通过CDN的方式引入Cesium,在ES6原生的js代码下进行模型加载,同样出现内存占用6.5G内存。
(4) 通过测试界面,对模型进行加载测试,发现也没有问题,所以也不会是模型本身数据量的问题。但是我同时发现了一个问题,那就是我明明在测试接口页面输入了 data.mars3d.cn/3dtiles/max-shihua/tileset.json,但是在控制台中,加载的竟然是 http://data1.mars3d.cn/3dtiles/max-shihua/tileset.json 地址的数据。
(5) 询问了ChatGPT之后,它给出了几点思路,有一点值得注意,就是如果模型本身存在问题,那么也有可能导致问题出现。

除了上面提到的内存占用问题之外,还有一个值得思考的问题,就是说官方在线的例子中,模型的加载速度通常会很快的,但是我本地进行数据加载测试的时候,会出现下载和模型显示特别的慢,这个可能也不是问题,就是作为一个记录好了。

1.官方在线版

官方在线的Vue版本, 这个示例中,内存消耗基本上稳定在898M上,不会随着时间的推移变动。

2.官方Vue版本

官方Vue版本 这个 示例 中,基本上维持在6.8G的样子。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
// 加载模型
let tiles3dLayer = new mars3d.layer.TilesetLayer({
name: "石化工厂",
url: baseUrl+"data/3dtiles/tileset.json",
position: { lng: 117.077158, lat: 31.659116, alt: 24.6 },
maximumScreenSpaceError: 1,
maximumMemoryUsage: 1024,

// 以下参数可以参考用于3dtiles总数据大,清晰度过高情况下进行性能优化。这不是一个通用的解决方案,但可以以此为参考。
skipLevelOfDetail: true,
loadSiblings: true,
cullRequestsWhileMoving: true,
cullRequestsWhileMovingMultiplier: 10,
preferLeaves: true,
dynamicScreenSpaceError: true,
preloadWhenHidden: true,
enableDebugWireframe: true, // 是否可以进行三角网的切换显示
// 以上为优化的参数

// popup: "all",
highlight: {
type: mars3d.EventType.click, // 默认为鼠标移入高亮,也可以指定click单击高亮
outlineEffect: true, // 采用OutlineEffect方式来高亮
color: "#00FF00"
},
center: { lat: 31.653047, lng: 117.084439, alt: 354, heading: 319, pitch: -23 },
flyTo: true
})
map.addLayer(tiles3dLayer)

3.官方ES5版本

官方es5版本,这个 示例 基本上要达到6.55G的样子。

4.Vue下原生Cesium加载

在Vue3框架下,使用原生的Cesium加载模型,虽然内存也还是在不断的上涨,但是涨的非常的慢,要过很长时间才能涨到6G。

5.ES6下原生Cesium加载

在ES6语法下,使用原生的Cesium加载模型,随着模型的不断加载,最后还是会导致内存飙升到6.5G。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
function initCesiumMap (){
// 构造地球(可以使用原生Cesium或第3方SDK方式去构造Viewer)
var tiandituTk='xxx';
// 服务负载子域
var subdomains=['0','1','2','3','4','5','6','7'];
const viewer = new Cesium.Viewer("app", {
animation: false,
timeline: false,
baseLayerPicker: false, // 是否显示图层选择控件
imageryProvider: new Cesium.WebMapTileServiceImageryProvider({
//影像底图
url: "http://t{s}.tianditu.com/img_w/wmts?service=wmts&request=GetTile&version=1.0.0&LAYER=img&tileMatrixSet=w&TileMatrix={TileMatrix}&TileRow={TileRow}&TileCol={TileCol}&style=default&format=tiles&tk="+tiandituTk,
subdomains: subdomains,
layer: "tdtImgLayer",
style: "default",
format: "image/jpeg",
tileMatrixSetID: "GoogleMapsCompatible",//使用谷歌的瓦片切片方式
})
})
let scene = viewer.scene;
var url="//data.mars3d.cn/3dtiles/max-shihua/tileset.json"

// 加载3d模型
const tileset = scene.primitives.add(
new Cesium.Cesium3DTileset({
url: url,
})
);
tileset.readyPromise
.then(function (tileset) {
// tileset的边界球
let boundingSphere = tileset.boundingSphere;
// 跳到边界球范围
viewer.camera.flyToBoundingSphere(boundingSphere);
// 绑定相机所在的位置:必须设置,否则左键移动变成单点定位
viewer.camera.lookAtTransform(Cesium.Matrix4.IDENTITY);
})
.catch(function (error) {
console.log(error);
});
}
// 初始化地图
initCesiumMap()

6.总结

通过测试界面,对模型进行加载测试,发现也没有问题,发现了一个问题,那就是我明明在测试接口页面输入了 //data.mars3d.cn/3dtiles/max-shihua/tileset.json,但是在控制台中,加载的竟然是 http://data1.mars3d.cn/3dtiles/max-shihua/tileset.json 地址的数据。同时结合ChatGPT给出的建议,可能是数据问题,于是我找到了问题的根本原因。

我将 http://data.mars3d.cn/3dtiles/max-shihua/tileset.json 下载下来,然后部署到了自己的服务器上,使用 测试界面,输入了自己的测试地址,发现同样的也会出现内存占用达到6.5G的效果。

所以问题就出在这个模型上,在data1.mars3d.cn上的模型,和data.mars3d.cn这个域名上的模型,并不是同一个模型,data1上的模型,应该是经过某种方式进行优化过了的。

7.模型优化

找到问题的原因了,那就需要在模型创建的时候,选择适当的方法,对模型进行优化。

参考文章:
1.Mars3d-如何处理3dtiles过大加载很慢的问题 1.数据处理层面,比如cesiumlab处理时的一些优化参数,优化压缩和数据结构。2.网络传输层面,nginx加gizp压缩,提高速度。3.JS代码层面,加一些参数在效果和效率中间取平衡值。
2.【003】-Cesium中加载大规模数据稳定流畅之性能优化思路 这里列举了很多的方法,但是主要的还是在代码层面进行的控制,没有说在切片的时候,如何选择相应的内容。1.使用数据流技术;2.使用LOD;3.使用Web Workers;4.使用空间索引;5.优化网络带宽;6.合并网格;7.纹理合批;8.纹理压缩;9.优化纹理加载;10.减少数据量;11.优化渲染管线;12.限制场景元素;13.缓存机制;14.延迟加载;15.其他优化技巧;16.避免频繁的内存分配;
3.cesium加载倾斜数据卡顿–cesiumlab–3dtiles
4.vue+cesium加载3dtiles模型内存消耗很大 viewer是写在组件的data下。想到vue框架会对组件的data里的数据都建立一个Watcher,有没有可能这样会把viewer保存下来,然后在移动视角的时候,viewer发生了改变,vue又不断的更新和保存viewer,然后viewer又是很占内存的,导致了内存的急剧增加
5.Cesium编程中内存占用的性能分析 通过浏览器的性能tab来分析,可以看到在哪个函数执行的时候,内存发生明显的增长。
小额赞助
本人提供免费与付费咨询服务,感谢您的支持!赞助请发邮件通知,方便公布您的善意!
**光 3.01 元
Sun 3.00 元
bibichuan 3.00 元
微信公众号
广告位
诚心邀请广大金主爸爸洽谈合作
每日一省
isNaN 和 Number.isNaN 函数的区别?

1.函数 isNaN 接收参数后,会尝试将这个参数转换为数值,任何不能被转换为数值的的值都会返回 true,因此非数字值传入也会返回 true ,会影响 NaN 的判断。

2.函数 Number.isNaN 会首先判断传入参数是否为数字,如果是数字再继续判断是否为 NaN ,不会进行数据类型的转换,这种方法对于 NaN 的判断更为准确。

每日二省
为什么0.1+0.2 ! == 0.3,如何让其相等?

一个直接的解决方法就是设置一个误差范围,通常称为“机器精度”。对JavaScript来说,这个值通常为2-52,在ES6中,提供了Number.EPSILON属性,而它的值就是2-52,只要判断0.1+0.2-0.3是否小于Number.EPSILON,如果小于,就可以判断为0.1+0.2 ===0.3。

每日三省
== 操作符的强制类型转换规则?

1.首先会判断两者类型是否**相同,**相同的话就比较两者的大小。

2.类型不相同的话,就会进行类型转换。

3.会先判断是否在对比 null 和 undefined,是的话就会返回 true。

4.判断两者类型是否为 string 和 number,是的话就会将字符串转换为 number。

5.判断其中一方是否为 boolean,是的话就会把 boolean 转为 number 再进行判断。

6.判断其中一方是否为 object 且另一方为 string、number 或者 symbol,是的话就会把 object 转为原始类型再进行判断。

每日英语
Happiness is time precipitation, smile is the lonely sad.
幸福是年华的沉淀,微笑是寂寞的悲伤。