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

本文涉及的产品
数据可视化DataV,5个大屏 1个月
可视分析地图(DataV-Atlas),3 个项目,100M 存储空间
简介: 我把文件重新编码后,加载速度提升300%!

原始代码涉及到一些PCD文件头处理等工作,由于这一部份和业务强相关,和本文所聊的压缩关系不大,所以我就把相关代码删了,只留下二进制转码相关的核心代码。

代码很短,应该不难看懂吧?看不懂的评论区举个手,我来给你手摸手教学下。

懒得看或者看不懂的,我作为课代表帮大家把关键点挑出来了,一起看看吧:

1. DataView2. CreateWriteStream

3. Buffer.from(dataview.buffer)

我先帮大家捋一捋整体流程,大致如下:

image.png

为什么我们没有用理想操作模型呢?两个文件流pipe一下,中间加一个转换器做一个编解码,搞定!多简单呀。

那是因为,当前这个场景不合适。

ThreeJS天然支持PCD文件的渲染,但前提是,必须有标准头,也就是这个东西。

image.png

有了头部元信息之后,剩下的部分就是「点云二进制」数据,ThreeJS天然支持。可以看下对应的源码:(https://github.com/mrdoob/three.js/blob/master/examples/jsm/loaders/PCDLoader.js

image.png

既然如此,那我们就可以把一个带有标准头的二进制文件直接丢给ThreeJS去渲染即可,ThreeJS会在运行时去解析,我们无需在服务端或者前端做多余的「解码」操作,节约渲染成本。

而如果采用理想模型,这意味着我们在转码Stream的每一个chunk的时候,是直接将chunk转成了二进制,并没有按「」为单位的去处理,毕竟NodeJS的chunk是按某个固定字节大小来分片的,而不是定制化的按「点」为分片单位。

这样的话,最终转出来的,仅仅是一个二进制文件,而不是一个ThreeJS可以识别的「点云二进制」文件,我们就必须在渲染之前先处理一遍数据,这就不太合适了。

当然了,如果是那么简单就能做的,也就不会有今天这篇文章了,也是因为这个特殊的处理场景,引入了一些比较有意思的知识点,所以才想分享给大家。

首先想想我们为什么要用DataView?DataView又是什么?一起看下MDN的解释:

DataView 视图是一个可以从二进制 ArrayBuffer 对象中读写多种数值类型的底层接口,使用它时,不用考虑不同平台的字节序(endianness)问题。

我们需要以「」为单位做编码,写入文件,那么也就是说,我们需要操作文件Buffer,而NodeJS为了防止安全和内存泄漏问题,是不允许直接操作Buffer本身的,于是提供了一个DataView接口,非常方便的操作ArrayBuffer

我们可以将每个「点」的信息逐一写入DataView:


point.forEach((axis, axisIndex) => {
  dataview.setFloat32(rowIndex * POINT_BYTES_SIZE + axisIndex * PARAMS_LENGTH, Number(axis), true)
})

这里我们用了setFloat32 ,因为xyzi四个参数每个都是4字节的浮点数,所以用float32来存,第一个参数是位偏移量,第二个是需要存的值,第三个是字节序(可选)。


dataview.setFloat32(byteOffset, value [, littleEndian])

对所有的点逐一处理之后,我们就拿到了一个存有完整点云信息的DataView,就可以拿去写文件了!

But!这里又有关键点了。你以为直接拿DataView的Buffer写入文件即可,如下:


wstream.write(dataview.buffer)

然后你就会看到报错:

image.png

为什么呢?

DataView的Buffer难道不是Buffer么?还真不是!你把鼠标挪到代码上一看:

image.png

好家伙,是个ArrayBuffer!没错,官方文档一开始就说了,DataView就是拿来操作ArrayBuffer的,没毛病。

那么怎么处理呢?其实稍微改一下就好啦:


wstream.write(Buffer.from(dataview.buffer))

Buffer.from 就可以直接把buffer转出来。

你可能有疑问了,从arrayBuffer转buffer我会了,那反过来呢?哈哈,其实一开始我们读源文件拿来做点云信息解析的时候,就已经这么干了,被我省略了代码,这里补上:


const inputData = fs.readFileSync(input)
const ab = inputData.buffer.slice(inputData.byteOffset, inputData.byteOffset + inputData.byt

看到没有,读取文件数据后,我们拿到的是一个buffer,而从buffer转arrayBuffer,只需要一个小小的slice即可,是不是很神奇。

到这里,其实我帮大家挑出来的关键点就都扯清楚了,最后还剩一个疑问,为啥要用createWriteStream 来写文件?有什么特殊考虑吗?

没错,其实一开始是想着,用「流」来写文件,性能更好,不会占用大量内存空间

但是上面也说了,我们不能简单的对接两头文件流,必须得把「」数据读出来逐个编码,那么势必就需要产生Buffer占用空间了,这样的话,Stream其实就变鸡肋了,完全可以直接替换成 fs.writeFileSync,而且writeFile还可以直接写DataView,更省事了呢!


fs.writeFileSync(output, dataview)

帮大家总结一下今天的几个小知识点:

1. NodeJS提供了一个DataView,用来操作Buffer,确切的说是 ArrayBuffer。

2. Buffer和ArrayBuffer可以互相转换。

3. Stream可以节约Buffer占用内存空间,但如果不利用好pipe,就等于失去了它的优势,还不如直接file操作。


啦!今天的分享就到这了,你学废了吗?

相关实践学习
DataV Board用户界面概览
本实验带领用户熟悉DataV Board这款可视化产品的用户界面
阿里云实时数仓实战 - 项目介绍及架构设计
课程简介 1)学习搭建一个数据仓库的过程,理解数据在整个数仓架构的从采集、存储、计算、输出、展示的整个业务流程。 2)整个数仓体系完全搭建在阿里云架构上,理解并学会运用各个服务组件,了解各个组件之间如何配合联动。 3 )前置知识要求   课程大纲 第一章 了解数据仓库概念 初步了解数据仓库是干什么的 第二章 按照企业开发的标准去搭建一个数据仓库 数据仓库的需求是什么 架构 怎么选型怎么购买服务器 第三章 数据生成模块 用户形成数据的一个准备 按照企业的标准,准备了十一张用户行为表 方便使用 第四章 采集模块的搭建 购买阿里云服务器 安装 JDK 安装 Flume 第五章 用户行为数据仓库 严格按照企业的标准开发 第六章 搭建业务数仓理论基础和对表的分类同步 第七章 业务数仓的搭建  业务行为数仓效果图  
目录
相关文章
|
6月前
|
开发工具
,这个问题可能是由于模型加载失败或者音频文件格式不正确导致的
,这个问题可能是由于模型加载失败或者音频文件格式不正确导致的
49 1
|
1月前
|
PyTorch TensorFlow API
大模型中 .safetensors 文件、.ckpt文件、.gguf和.pth以及.bin文件区别、加载和保存以及转换方式
本文讨论了大模型中不同文件格式如`.safetensors`、`.ckpt`、`.gguf`、`.pth`和`.bin`的区别、用途以及如何在TensorFlow、PyTorch和ONNX等框架之间进行加载、保存和转换。
345 2
|
编解码 JSON 缓存
我把文件重新编码后,加载速度提升300%!(上)
我把文件重新编码后,加载速度提升300%!
102 0
|
Java
小程序中base64解码/编码
很多人都在为小程序如何实现base64编码/解码困扰,于是我参考前端大佬们对JavaScript中实现base64的文章进行了改写。简单实现了一个。。希望能帮助到小程序开发一线的大家吧、 不多说直接上代码: /** * UTF16和UTF8转换对照表 * U+00000000 – U+000000...
4901 13
AVI格式视频文件编码格式缺少编码解释器且该项目的编码格式不受支持(0xc00d5212错误)
AVI格式视频文件编码格式缺少编码解释器且该项目的编码格式不受支持(0xc00d5212错误)
3094 0
AVI格式视频文件编码格式缺少编码解释器且该项目的编码格式不受支持(0xc00d5212错误)
|
编译器 Shell Linux
VS2019 高级保存设置UTF-8编码-源代码乱码问题
VS2019 高级保存设置UTF-8编码-源代码乱码问题
1250 0
VS2019 高级保存设置UTF-8编码-源代码乱码问题