一百万条轨迹,页面直接崩了
CSV 解析完内存就到 2.4 GB,浏览器标签页变白,标题变成“页面无响应”。
现象
加载 120 万条 GPS 记录后,控制台报内存分配失败,页面崩溃:
Uncaught RangeError: Array buffer allocation failed
at new Float32Array (<anonymous>)
at TripsLayer.initializeState (trips-layer.js:88)
内存面板里 JS 堆持续上涨,GC 后仍不回落,说明数据被长期持有。
原因
用 d3.csv 或 papaparse 解析后得到的是对象数组,
每行对象连同属性名、字符串值大约 200–400 字节。120 万行就是 400 MB 以上。
deck.gl 在更新时还会保留上一份数据做差分,峰值接近两倍。
TripsLayer 的 getPath 返回普通数组,
每个点再创建一个小数组对象,又叠加一轮开销。
排查过程
- 在
onDataLoad里打印记录数与内存占用。 - 用
performance.memory.usedJSHeapSize对比解析前后。 - 只保留 10 万条做对照,确认崩溃点是数量级而不是某条脏数据。
console.log('记录数', data.length);
console.log('堆内存 MB', (performance.memory.usedJSHeapSize / 1048576).toFixed(1));
解决方案
方案一:改用二进制属性,把经纬度、时间、颜色压进 Float32Array。
同样一百万条,内存从 400 MB 降到几十 MB:
var count = 1200000;
var positions = new Float32Array(count * 2); // [lng, lat]
var timestamps = new Float32Array(count);
for (var i = 0; i < count; i++) {
positions[i * 2] = rows[i][0];
positions[i * 2 + 1] = rows[i][1];
timestamps[i] = rows[i][2];
}
var layer = new deck.ScatterplotLayer({
id: 'gps',
data: {
length: count,
attributes: {
getPosition: { value: positions, size: 2 },
getTimestamp: { value: timestamps, size: 1 }
}
},
getRadius: 2,
radiusUnits: 'pixels',
getFillColor: [0, 160, 255]
});
方案二:按时间或空间分块,只加载当前视野与当前时段的数据。 这是数据量再大也能维持交互的做法:
function loadChunk(tileKey) {
fetch('/api/gps?tile=' + tileKey)
.then(function (r) { return r.arrayBuffer(); })
.then(function (buf) {
var positions = new Float32Array(buf);
overlay.setProps({
layers: [makeLayer(positions)]
});
});
}
map.on('moveend', function () {
loadChunk(currentTileKey(map.getBounds()));
});
方案三:轨迹层改用预计算的分段数据,避免在访问器里临时拼数组:
new deck.TripsLayer({
id: 'trips',
data: binaryTrips,
getPath: function (d) { return d.path; }, // 预先构造成扁平数组
getTimestamps: function (d) { return d.timestamps; },
getColor: [253, 128, 93],
widthMinPixels: 2,
trailLength: 180,
currentTime: 3600
});
验证
加载同等数据后,堆内存稳定在 150 MB 以内,不再出现
Array buffer allocation failed。
缩放与旋转保持 30 fps 以上,切到别的时段再切回,内存不持续上涨。
先看数据表示:大部分“deck.gl 内存爆”不是渲染问题, 而是把 CSV 对象数组直接喂给图层。把对象数组换成 typed array, 通常一行改动就能解决大半。
经纬志(2026)。《一百万条轨迹,页面直接崩了》。https://www.jingweizhi.com/cookbook/deckgl-oom-large-data.html(访问日期 2026-11-03)。