当前位置: 首页 > Web前端 > HTML5

你要的WebAssembly介绍与实践

时间:2023-04-05 19:21:19 HTML5

写在开头。不想为了跟风而学习某项技术。我只做最基本的介绍和实用的解释。欢迎收藏前端生活社区:https://qianduan.life想加入资源群和前端交流群可以看看文末什么是WebAssembly,能吃吗?官网介绍:WebAssembly是由主流浏览器厂商组成的W3C社区组制定的新规范。WebAssembly/wasmWebAssembly或wasm是一种可移植、体积小、加载速度快且与Web兼容的新格式。WebAssembly的特性EfficientWebAssembly有一套完整的语义。事实上,wasm是一种二进制格式,体积小,加载速度快。其目标是充分发挥硬件能力,达到原生执行效率。安全的WebAssembly在沙盒执行环境中运行,甚至可以在机器中实现的现有JavaScript虚拟机上运行。在web环境中,WebAssembly会严格遵守同源策略和浏览器安全策略。OpenWebAssembly被设计为一种非常规的文本格式,用于调试、测试、实验、优化、学习、教学或编写程序。wasm模块的源代码可以在网页上以这种文本格式查看。标准的WebAssembly被设计为无版本、可测试特性和在网络上向后兼容。WebAssembly可以被JavaScript调用,进入JavaScript上下文,也可以像WebAPI一样调用浏览器函数。当然,WebAssembly不仅可以运行在浏览器上,也可以运行在非Web环境中。正式开始(凑字数,懂了)Node.js有C++插件,Addon模块,也可以调用C#插件,go插件,和它们通信。让我展示一段我以前写的代码。用子进程调用c#插件,然后进行通信。(其实这是我当时写的windows平台的截图,插入自研的文本编辑器,桌面软件)`//Node.js主进程调用子进程awaitscreen_window();//functionscreen_windowimport{execFile}from'child_process';importpathfrom'path';importipcSendfrom'../main/utils/ipcSender';functionscreen_window(){returnnewPromise((resolve,reject)=>{constscreen_window=execFile(path.resolve($dirname,'../screenshot/PrintScr.exe'));screen_window.on('exit',function(code){if(code===1){ipcSend.insertImage();}resolve();});});}exportdefaultscreen_window;`既然Node.js有扩展能力,那浏览器环境呢?还必须要处理一个speex格式的音频,在H5中实现动态播放。我封装了一个7000行的库,里面有很多八进制的。。。泪目,但是最后帮助了很多人,希望对你有用https://github.com/JinJieTan/speex-in-h5在处理音视频的时候,考虑各种插件,webAssembly...什么时候需要考虑使用webAssembly?首先给大家一个链接,https://www.wasm.com.cn/demo/Tanks/,这就是坦克!Unity教程中的一个游戏导出为WebAssembly游戏。它非常光滑如丝般光滑。你是怎么理解webAssembly这个技术的?写到这里很多人还是不明白,webAssembly究竟是什么!Node.js可以直接运行C#C++代码吗?当然不是,只能调用操作系统的能力,或者+中间层或者其他方式调用浏览器运行C++代码,rust?当然不可以(如果可以告诉我,我这里改)那么,webAssembly模块必须编译成浏览器可以识别的语言,然后被JS调用,才算是同一种形式作为C++ADDON,我个人的理解是,在这里,我想强调一件事。虽然Electron中有主进程和渲染进程,但是如果主进程被阻塞,渲染进程也会被阻塞,GC也会被阻塞。1秒回收300MB需要多长时间?忘了,去年做过实验,所以在浏览器中,在调用webAssembly模块的情况下,理论上如果webAssembly模块被阻塞,那么JS主解析线程也会被阻塞。但是我在国外网站上看到的是:每个WebAssembly线程都运行在WebWorker中,相当于脱离了JS主解析线程,不会阻塞JS主线程的解析。SharedArrayBuffer和原子操作使开发人员能够跨多个线程使用共享内存。这样就可以实现更细粒度的并发算法,避免太硬核带来的不适感。可以跳转到https://hacks.mozilla.org/2017/06/a-crash-course-in-memory-management/how编写webAssembly模块,复制以下代码到浏览器控制台运行WebAssembly.compile(新的Uint8Array(`0061736d01000000010c0260027f7f017f60017f017f0303020001071002036164640000067561710a13020800200020016a0f0b0800200020006c`s./[\s\r\n]+/g).map(str=>parseInt(str,16)))).then(module=>{constinstance=newWebAssembly.Instance(module)const{add,square}=instance.exportsconsole.log('2+4=',add(2,4))console.log('3^2=',square(3))console.log('(2+5)^2=',square(add(2+5)))})``输出结果:这里应该可以看到那个webAssembly模块其实就是你写的webAssembly模块的一个二进制文件,不管是什么语言,都应该是一个二进制文件,然后前端通过ajax得到,如何编译:https://www.wasm.com.cn/getting-started/developers-guide/如何加载/运行webAssembly模块?在未来的计划中,WebAssembly模块可以使用ES6模块(使用)加载,WebAssembly目前只能通过JavaSc使用ript加载和编译基本加载,只需要3步:获取.wasm二进制文件,将其转换为类型化数组或ArrayBuffer,将二进制数据编译成WebAssembly.Module,使用imports实例化这个WebAssembly.Module,并获得出口。webAssembly模块使用示例:首先定义加载webAssembly的函数:`/***@param{String}pathwasm文件路径*@param{Object}imports传递给wasm代码中的变量*/functionloadWebAssembly(path,imports={}){returnfetch(path).then(response=>response.arrayBuffer()).then(buffer=>WebAssembly.compile(buffer)).then(module=>{imports.env=imports.env||{}//开辟内存空间imports.env.memoryBase=imports.env.memoryBase||0if(!imports.env.memory){imports.env.memory=newWebAssembly.Memory({initial:256})}//创建变量映射表imports.env.tableBase=imports.env.tableBase||0if(!imports.env.table){//元素在MVP版本imports.env中只能是“anyfunc”。table=newWebAssembly.Table({initial:0,element:'anyfunc'})}//创建一个WebAssembly实例returnnewWebAssembly.Instance(module,imports)})}`然后外部调用并传入资源存储此WebAssembly模块的接口`loadWebAssembly('path/to/math.wasm').then(instance=>{const{add,square}=instance.exports//...})`只要通过request获取,然后处理,就可以获取到exports的内容。想深入了解可以参考webAssembly和ffmpeg实现前端转码导出一个入口函数给上层js传入函数参数控制ffmpeg命令行参数通过虚拟文件传入输入文件系统并获取输出文件https://zhuanlan.zhihu.com/p/27910351使用方法:`self.importScripts('ffmpeg.js');onmessage=function(e){console.log('ffmpeg_run',ffmpeg_run);var文件=e.data;控制台日志(文件);ffmpeg_run({参数:['-i','/input/'+files[0].name,'-b:v','64k','-bufsize','64k','-vf','showinfo','-strict','-2','out.mp4'],files:files,},function(results){console.log('result',results);self.postMessage(结果[0].data,[results[0].data]);});}`说到转码和压缩,应该多考虑webAssembly。当然node.js本身也可以通过传参调用ffmpeg。对于图像压缩之类的事情,Node.js做不好,就算是C++插件,CPU也是很饿的,并发稍微高一点,CPU就100%了。欢迎关注我的公众号:前端巅峰

最新推荐
猜你喜欢