本周的 wasm 大新闻莫过于阮老师发的一条 twitter:
厉害了,Windows 2000 被编译成 WebAssembly,可以在浏览器里跑了。https://t.co/CdLH3hB1Ru pic.twitter.com/wAWkuCoUTd
— ruanyf (@ruanyf) 2018年8月21日
体验下来确实很惊艳,大家都开玩笑说终于可以在 Chrome 里打开 Firefox 了,只是需要一点耐心 hmm…
不过,阮老师又一次搞了个大新闻,Windows 虽然底层是有很多 C 代码,但并不像 Linux 开源,既然都拿不到源码又何来被编译成 wasm 之说呢? 那真相是什么样子呢?作者 Fabrice Bellard 又是何方大神?
Windows 2000 on JSLinux
在这个页面底部的 Technical notes 链接里,我们可以找到一些技术细节。原来背后是 Bellard 开发的 JSLinux 这个东西,它是一个用 JavaScript 编写的可以运行在浏览器环境的模拟器,大概可以类比到 vmware/virtualbox。算下来接近 8 个年头了,2011 年时 Bellard 编写了初代版本的 JSLinux,也是用 JavaScript 编写的可以跑 Linux 的首个 PC/x86 的模拟器,复用了 Bellard 另一个牛逼的工具 QEMU 实现 x86 的辅助功能和设备模拟。
之后在 2015 年切换到使用 asm.js 来提升性能,2016 年在开发 riscvemu (一个 RISC-V 模拟器) 后,Bellard 决定使用 emscripten 从 C 代码输出 JavaScript 版本,并且还开发了 VirtIO 9P 文件系统便于使用远程文件系统以及文件导入导出,接下来 Bellard 发现复用 VirtIO 设备到 x86 JS 模拟器很有趣,于是把 JSLinux 的 asm.js 版本的代码转为 C 再通过 emscripten 转回 JavaScript,通过细致的调优之后新的版本比原来手写的 asm.js 版本更快了。
这之后 JSLinux 就不再只局限于 Linux 系统了,开始向 Windows NT 进军了,当前版本的 JSLinux 模拟了缺失的几个 PC 设备(PS/2 键鼠、VGA 等),已经可以运行 Windows NT 了。
说了这么多,那到底真相是什么呢?找到一张图,虽然不是直接相关(《jsmodem - 讓 jslinux 使用網路功能》,讲的是 JSLinux 里模拟 modem 的实现),大体也差不多了:
简单说大约是 JSLinux 跑在浏览器的 JS 引擎之上,提供一层虚拟机,然后加载了 Windows 2000 的系统跑了起来。当然实际细节要复杂得多,如果你打开浏览器控制台,观察一下请求,会发现初始阶段加载的 wasm 其实体积并不大,后面会不断异步拉取 .bin
文件,看起来是基于 Windows 2000 的镜像做了细粒度的拆分,而且在交互上也会发现随着交互的进行,源源不断会阻塞去按需加载新的 .bin
文件回来。
话说回来其实 JSLinux 支持 Windows 2000 是 去年 9 月的事情了,这周突然在社区热闹起来大约是因为大佬 Steven Sinofsky (前微软 Windows 事业部总裁)的 twitter, 加上阮老师应该也是看了下面这条来自 WebAssemblyWeekly 公共账号 的传播。相比去年主要就是模拟器部分开始有了 wasm 的支持,所以得到了大家的关注和 wasm 社区的雀跃。
Window 2000 emulated in WebAssembly https://t.co/l7f8au2Zk5 pic.twitter.com/U9fg3w3ZRh
— WebAssemblyWeekly (@WasmWeekly) 2018年8月21日
Fabrice Bellard 大神
接下来简单八一下作者 Fabrice Bellard 大神,前面的介绍里已经多次说到 Fabrice Bellard 大神各种造工具的记录了,这位大神到底什么来头?他还有些什么杰作?知乎上有个问题:《Fabrice Bellard是个什么水平的程序员?》,搬运一下:
作者:Hao Lee
链接:https://www.zhihu.com/question/28388113/answer/150897437
来源:知乎
著作权归作者所有。商业转载请联系作者获得授权,非商业转载请注明出处。
确实是奇才, 单是 FFmpeg 和 Qemu 这两项就足以超越绝大部分程序员了。看到他的成就我的第一反应就是这哥们儿能和 Linus Torvalds 拼一下(不一定干得过,企鹅王体型比他大)。Fabrice Bellard 的计算机底层功力极其深厚,对各种细节了如指掌,虚拟机可不是想写就能写的,这需要熟悉CPU、内存、BIOS、磁盘的内部原理,鼠标、键盘、终端等外围设备的工作流程,然后在软件层面模拟出来,想想就复杂。从这一点上他可以被称作天才程序员。另外,他的数学功底也是相当扎实,能发现计算圆周率的新算法并且改进算法的人又可以称作计算机科学家。他一个人几乎涵盖了计算机领域的两大发展路线,属于那种全才型的人物。我等只能仰视,无可企及。
下面,让我们来按照时间顺序看一看大神的人生轨迹:
- 1972年,天才降生
- 上大学之前重写了LZSS压缩算法,解压软件速度快体积小
- 1997年1月20日,他发布了最快速的计算圆周率的算法,此算法是 Bailey-Borwein-Plouffe 公式的变体,前者的时间复杂度是O(n^3),他给优化成了O(n^2),使得计算速度提高了43%,这是他在数学领域的成就。此时他仅有25岁,我特么现在还在玩泥巴。
- 2000年他化名Gérard Lantau,创建了FFmpeg项目,做过多媒体音视频处理的应该都知道这个项目到底有多强大。现在暴风影音、QQ影音、格式工厂,还有YouTube、VLC等都使用了FFmpeg的编解码函数库,不过前三者因为不遵守开源协议已经被FFmpeg挂在官网昭告天下了(官网的页面不知为何下线了,我找了份存档 https://web.archive.org/web/20101214233906/http://ffmpeg.org/shame.html)。FFmpeg易扩展、功能强、速度快、占资源少,支持的音视频格式极其广泛,基本上超越了其他所有同类软件,这是他在多媒体处理领域的巨大成就。
- 2000-2001年左右,他赢得两次国际混淆C代码大赛(IOCCC),第一个作品写了个4KB大小的C语言编译器子集 OTCC ,这可以算作是TinyCC的前身;第二个作品写了个475B大小的用于打印已知最大素数的程序,用傅里叶变换做的,膜拜吧。
- 2002年他发布了TinyGL,这是OpenGL的一个子集实现,体积小速度快,占资源还少,这是他在图像处理领域的成就。
- 2003年开发了Emacs的一个变种:QEmacs。
- 2004年8月他在之前OTCC的基础上继续完善,使之具备了能够编译Linux内核的能力,这就是TinyCC的正式版,简称TCC。为了证明TCC的威力,他又写了一个只有138KB的启动加载程序TCCBOOT,可以在15秒内从源代码编译并启动Linux内核。分分钟就写了个编译器加引导器,怎么样,怕不怕,我已经躲在角落瑟瑟发抖了。
- 2005年,Bellard 发布了 QEMU,这是个爆炸性的项目,现在众多底层开发人员已经离不开它了,相当的强大,操作系统教学领域也多用其作为演示。开发这玩意儿需要非常广泛的底层硬件和操作系统知识,一般人搞不定。QEMU的技术已经被应用于KVM、XEN、VirtualBox等多个虚拟化项目中。他至少领导了QEMU项目4年,这是他在虚拟化领域的成就。同年,他用普通PC和VGA卡设计了一个数字电视系统。
- 2009年12月31日,他声称打破了圆周率计算的世界纪录,仅用一台普通PC机,耗时116天,算出了圆周率小数点后2.7万亿位,比2009年8月17日由超级计算机算出的世界纪录多了1200亿位 。凭借这个突出的数学贡献,他登上了《科学美国人》法文版。
- 2011年,他单用JavaScript写了一个PC虚拟机Jslinux 。这个虚拟机仿真了一个32位的x86兼容处理器,一个8259可编程中断控制器,一个8254可编程中断计时器,和一个16450 UART。想玩的来这里:Javascript PC Emulator。我觉得他写这玩意儿的时候头顶已经出现光环飘飘乎羽化而登仙了。
- 不得不承认,这个世界真的有天才。
wasm 还有哪些惊艳的 demo
最近 wasm 1.0 版本的草案 终于发布,wasm 官网 上也挂出了四大主流浏览器已提供 1.0 版本支持的消息。Ending定律也将开始生效。算起来从 2015 年 4 月 WebAssembly 社区工作组 成立到现在,wasm 才 3 岁,除了 Windows 2000,还有哪些惊艳的 wasm 的 demo 呢?
- vim.wasm,demo 地址
- webDSP,demo 地址
- JSC.js,demo 地址
- 官方坦克大战 demo
- EpicZenGarden,3D 大作
- Autodesk,今年的 Google I/O 2018 大会上还做了 专题分享
- JavaScript vs wasm animation,可以直观感受两者的性能对比
- GameBoy 模拟器,这有一个口袋妖怪的 rom
- Funky Karts,demo,这里还有详细的实现介绍
总的来说可以看到由于有众多的 C/C++/Rust 开发的现有游戏可以通过编译到中间语言(IR),继而编译到 wasm,如下图 Lin Clark 在 wasm 系列文章之一 《Creating and working with WebAssembly modules》 中的下图所示,这让移植成本变得相对轻松,也不奇怪看到很多 Rust 的游戏可以转到 wasm 版本。
Lifoff in V8
另一条值得关注的与 wasm 有关的是 V8 官方博客的更新:《Liftoff: a new baseline compiler for WebAssembly in V8》。在 V8 6.9 之前,wasm 在 V8 里的运行只能在 TurboFan 编译器上,而 TurboFan 本身是为高性能执行而设计,短板是启动性能(因为要做深入优化,代码生成速度慢),在 JS 的执行时 V8 里有 Ignition 编译器作为基线编译器(baseline compiler)来解决快速启动和内存占用的问题,而在 wasm 里则没有,因此这次引入了一个新的基线编译器 Liftoff 来解决 wasm 的快速启动问题。
通过博客上这张图可以看到,相比 TurboFan,Liftoff 的代码生成效率要高得多,而且博文中介绍到可以在解码和验证函数体的同时不断地执行代码生成,基于 wasm 的流式处理 API,可以使 V8 在通过网络下载 wasm 的同时将 wasm 代码不断编译到机器码,加快启动执行效率。
从后文的图也可以看出性能提升也是相当明显的。
接下来还会有更多的优化,比如目前 Liftoff 还仅支持 Intel 平台 主要覆盖桌面用户,接下来会移植到 arm 和 arm64 以支持移动设备;针对移动设备可用内存更少的情况实现动态的编译层级提升;提升 Liftoff 的代码生成性能以及生成的代码的性能等。
结
随着 1.0 草案的落地,四大主流浏览器的支持,今年大概真的可以算 wasm 元年了。浏览器里跑操作系统都已经不是梦,AutoDesk 也可以搬到浏览器里,未来还有什么是不可取代的 B/S 呢?当然另一方面也意味着前端的版图已经越来越广阔,要学的东西更多了,如果你对 wasm 还没有多少了解,不妨从 Lin Clark 的 《A cartoon intro to WebAssembly》 看起(中文翻译版可以参见:https://www.w3ctech.com/topic/2027),浅显易懂,非常推荐。
以上。如有谬误,敬请指正。
评论