我把文件重新编码后,加载速度提升300%!(上)

简介: 我把文件重新编码后,加载速度提升300%!

3个月前,我写过一篇关于性能优化的方法论(《前端性能优化思想模型,在自动驾驶领域的实践》),里面有提到过,我对PCD文件进行二进制转码处理后,效果非常好。

但那篇文章主要是分享方法论思想模型,并没有展开聊细节,所以估计很多入门小伙伴看都懒得看就划走了,或者看完没有太多感觉,糊里糊涂的也没多大收获。

我写的东西晦涩难懂,帮不到大家,这怎么能行?这是我的耻辱

那么今天我就拿其中一个案例来展开聊聊,用最通俗的语言,给你抽丝剥茧讲明白。

先看效果!

转码前后文件尺寸对比:(17.8MB vs 4.6MB,压缩率75%

image.png

转码页面加载效果:(ASCII编码,2倍速播放,18秒)

image.png

转码后页面加载效果(二进制编码,2倍速播放,5秒)

image.png

之前也提到过,在自动驾驶点云标注场景下,一次需要加载几十帧的数据文件,如果每一帧文件都是动辄十几二十MB,那即便做异步加载,等待时间之久也是相当令人头大的。

性能优化迫在眉睫!

好,我们先来盘点一下前端手里能用的几个性能优化法宝:

1. 异步加载2. 分片加载,增量渲染3. 资源文件压缩

4. 缓存

本文暂且只讲3,124就先跳过不聊了,之所以摆在这里是想给大家一点启发,告诉你,还有这么些个优化方法呢,感兴趣的评论区交流,最好是关注我,追更,也给我一些动力。

来,我们继续。

聊到文件压缩,不得不提一件有意思的往事。很多人问我,我网名为啥叫ASCII26

那是因为,大学时候学到著名的哈夫曼编码(Huffman Coding),老师给我们布置了一道作业,用哈夫曼编码压缩一段超长文本,比如一部小说。

我觉得这事儿很有意思,就吭哧吭哧开始写算法,写完一运行,文件确实压小了不少,正得意呢,突然发现,压缩文件反向解码的时候出错了,解出来的文件出现了乱码。

这个问题让我定位了好久好久,没日没夜反复调试,怎么都找不到bug在哪。直到有一天,我发现我编码的文本里有一个鬼东西,原文中肉眼不可见,编码后是一个极其容易被忽视的小红点,我用代码读它,发现这东西的ASCII编码值是26。

当然了,是什么原因导致的bug,以及我怎么解决的,我都记不清了(已经十多年了),我只记得,从那天起,我把所有的网名全都变成了ASCII26,算是一个纪念吧,纪念我呕心沥血独自解决了一个难题,也纪念我对编程这件事仍充满着热爱

扯这个小故事给大家放松下,同时,这个小故事本身也是编解码相关。

好啦,回到正题。

那么这次我们要编解码什么呢?我们先来看下我们要处理的文件长什么样。

image.png

这就是PCD文件(自动驾驶点云文件)的冰山一角,其中,1-11行是它的标准头部信息,而12行之后,便是无穷无尽可随意扩展的点云数据。

这里简单提一嘴,有的产商提供的点云数据直接就是bin文件,而有的是pcd文件,还有的甚至是JSON文件,总之,国内的自动驾驶行业现状非常混乱,工程团队素质良莠不齐。

知道PCD文件头部元信息之后,我们把它取出来备用,这一小部分并不会占用太多体积,压不压缩都无所谓,压缩反而不利于后期直接在ThreeJs里引用。

而真正影响文件体积的,是12行之后的点云数据(几十万行),我们观察这一部份的构成,每一行是一个点的信息,用空格分割,分别代表着x,y,zintensity(头部元信息告诉我们的)。

image.png

那么我们要做的就是逐行扫描点云数据,分别将4个参数转写为二进制数据,存入 DataView 中,再使用NodeJS文件流APIcreateWriteStream 将数据写入目标文件,核心代码如下:


// ...省略部分代码
const PARAMS_LENGTH = 4; // [x, y, z, i].length
const AXIS_BYTES_SIZE = 4;
const POINT_BYTES_SIZE = PARAMS_LENGTH * AXIS_BYTES_SIZE;
// 创建一个dataView,窗口长度初始化为 点云数量 * 16 (从头部文件信息可知,一行4个参数,每个参数占4个字节)
const dataview = new DataView(new ArrayBuffer(POINT_BYTES_SIZE * points.length));
points.forEach((pointString, rowIndex) => {
  // 将点从字符串中取出来,即'x y z i' => [x, y, z, i]
  const point = pointString.split(' ');
  // 逐个参数处理,塞入dataview中
  point.forEach((axis, axisIndex) => {
    dataview.setFloat32(rowIndex * POINT_BYTES_SIZE + axisIndex * PARAMS_LENGTH, Number(axis), true)
  })
})
const wstream = fs.createWriteStream(output, 'binary');
// 写回头部信息
wstream.write(getPCDHeaderString(points.length))
// 写入点云信息
wstream.write(Buffer.from(dataview.buffer))
wstream.end(() => console.log('写入成功!'));
相关实践学习
基于Hologres轻量实时的高性能OLAP分析
本教程基于GitHub Archive公开数据集,通过DataWorks将GitHub中的项⽬、行为等20多种事件类型数据实时采集至Hologres进行分析,同时使用DataV内置模板,快速搭建实时可视化数据大屏,从开发者、项⽬、编程语⾔等多个维度了解GitHub实时数据变化情况。
阿里云实时数仓实战 - 用户行为数仓搭建
课程简介 1)学习搭建一个数据仓库的过程,理解数据在整个数仓架构的从采集、存储、计算、输出、展示的整个业务流程。 2)整个数仓体系完全搭建在阿里云架构上,理解并学会运用各个服务组件,了解各个组件之间如何配合联动。 3 )前置知识要求:熟练掌握 SQL 语法熟悉 Linux 命令,对 Hadoop 大数据体系有一定的了解   课程大纲 第一章 了解数据仓库概念 初步了解数据仓库是干什么的 第二章 按照企业开发的标准去搭建一个数据仓库 数据仓库的需求是什么 架构 怎么选型怎么购买服务器 第三章 数据生成模块 用户形成数据的一个准备 按照企业的标准,准备了十一张用户行为表 方便使用 第四章 采集模块的搭建 购买阿里云服务器 安装 JDK 安装 Flume 第五章 用户行为数据仓库 严格按照企业的标准开发 第六章 搭建业务数仓理论基础和对表的分类同步 第七章 业务数仓的搭建  业务行为数仓效果图  
目录
相关文章
|
存储
matlab求解方程和多元函数方程组
matlab求解方程和多元函数方程组
1488 0
|
机器学习/深度学习 Web App开发 编解码
最高增强至1440p,阿里云发布端侧实时超分工具,低成本实现高画质
近日,阿里云机器学习PAI团队发布一键端侧超分工具,可实现在设备和网络带宽不变的情况下,将移动端视频分辨率提升1倍,最高可增强至1440p,将大幅提升终端用户的观看体验,该技术目前已在优酷、夸克、UC浏览器等多个APP中广泛应用。
最高增强至1440p,阿里云发布端侧实时超分工具,低成本实现高画质
|
11月前
|
缓存 异构计算
DashInfer-VLM,多模态SOTA推理性能,超vLLM!
DashInfer-VLM是一个针对于视觉多模态大模型VLM的推理架构,特别优化了Qwen VL模型的推理加速,DashInfer-VLM和其他的VLM的推理加速框架最大的区别是, 它把VIT部分和LLM部分进行了分离,并且VIT和LLM的运行是并行运行,不互相干扰。
1470 16
|
前端开发 JavaScript Java
基于Java+Springboot+Vue开发的母婴商城管理系统
基于Java+Springboot+Vue开发的母婴商城管理系统(前后端分离),这是一项为大学生课程设计作业而开发的项目。该系统旨在帮助大学生学习并掌握Java编程技能,同时锻炼他们的项目设计与开发能力。通过学习基于Java的网上母婴商城管理系统项目,大学生可以在实践中学习和提升自己的能力,为以后的职业发展打下坚实基础。
268 7
基于Java+Springboot+Vue开发的母婴商城管理系统
|
定位技术 数据处理
合成孔径SAR雷达成像成(RDA和CSA)(Matlab代码实现)
合成孔径SAR雷达成像成(RDA和CSA)(Matlab代码实现)
435 0
|
前端开发 JavaScript UED
|
监控 关系型数据库 MySQL
zabbix 简单介绍 及部署
zabbix 简单介绍 及部署
|
算法
Threejs中使用astar(A*)算法寻路导航,Threejs寻路定位导航
Threejs中使用astar(A*)算法寻路导航,Threejs寻路定位导航
991 0
Threejs中使用astar(A*)算法寻路导航,Threejs寻路定位导航
|
存储 数据挖掘 关系型数据库
DataFrame 与数据库交互:从导入到导出
【5月更文挑战第19天】本文介绍了如何在数据分析中实现DataFrame与MySQL数据库之间的数据交互。通过`pandas`的`read_sql`函数可将数据库中的数据导入DataFrame,处理后使用数据库游标执行插入或更新操作将数据导回。注意数据类型匹配、数据完整性和一致性。对于大量数据,可采用分块读取和批量操作提升效率。这种交互能结合数据库的存储管理和DataFrame的分析功能,提高数据处理效率。
508 2