JavaScript是如何工作的:与WebAssembly比较及其使用场景

*摘要:** WebAssembly未来可期。

  • 原文:JavaScript是如何工作的:与WebAssembly比较及其使用场景
  • 作者:前端小智

Fundebug经授权转载,版权归原作者所有。

这是专门探索 JavaScript及其所构建的组件的系列文章的第6篇。

如果你错过了前面的章节,可以在这里找到它们:

  • JavaScript是如何工作的:引擎,运行时和调用堆栈的概述!
  • JavaScript是如何工作的:深入V8引擎&编写优化代码的5个技巧
  • JavaScript如何工作:内存管理+如何处理4个常见的内存泄漏
  • JavaScript是如何工作的:事件循环和异步编程的崛起+ 5种使用 async/await 更好地编码方式!
  • JavaScript是如何工作: 深入探索 websocket 和HTTP/2与SSE +如何选择正确的路径!

这次将讲解WebAssembly是如何工作的,更重要的是,它是如何在性能方面与JavaScript进行比较的:加载时间、执行速度、垃圾收集、内存使用、API开放平台、调试、多线程和可移植性。

首先,让我们看看WebAssembly做什么

首先,我们有必要了解一下asm.js。2012年,Mozilla 的工程师 Alon Zakai 在研究 LLVM 编译器时突发奇想:许多 3D 游戏都是用 C / C++ 语言写的,如果能将 C / C++ 语言编译成 JavaScript 代码,它们不就能在浏览器里运行了吗?众所周知,JavaScript 的基本语法与 C 语言高度相似。于是,他开始研究怎么才能实现这个目标,为此专门做了一个编译器项目 Emscripten。这个编译器可以将 C / C++ 代码编译成 JS 代码,但不是普通的 JS,而是一种叫做 asm.js 的 JavaScript 变体,性能差不多是原生代码的50%

之后Google开发了Portable Native Client,也是一种能让浏览器运行C/C++代码的技术。 后来可能是因为彼此之间有共同的更高追求,Google, Microsoft, Mozilla, Apple等几家大公司一起合作开发了一个面向Web的通用二进制和文本格式的项目,那就是WebAssembly。asm.js 与 WebAssembly 功能基本一致,就是转出来的代码不一样:asm.js是文本,WebAssembly是二进制字节码,因此运行速度更快、体积更小

WebAssembly(又称 wasm) 是一种新的字节码格式,主流浏览器都已经支持 WebAssembly。 和 JS 需要解释执行不同的是,WebAssembly 字节码和底层机器码很相似可快速装载运行,因此性能相对于 JS 解释执行大大提升。 也就是说 WebAssembly 并不是一门编程语言,而是一份字节码标准,需要用高级编程语言编译出字节码放到 WebAssembly 虚拟机中才能运行, 浏览器厂商需要做的就是根据 WebAssembly 规范实现虚拟机。

WebAssembly 加载时间

WebAssembly在浏览器中加载速度更快,因为只有已经编译好的wasm文件需要通过internet传输。wasm是一种低级汇编语言,具有非常简洁的二进制格式。

WebAssembly 执行速度

如今 Wasm运行速度只比原生代码慢20%,这是一个令人惊喜的结果。它是这样的一种格式,会被编译进沙箱环境中且在大量的约束条件下运行以保证没有任何安全漏洞或者使之强化。和真正的原生代码比较,执行速度的下降微乎其微。更重要的是,未来将会更加快速。

更好的是,它与浏览器无关——所有主要引擎都增加了对WebAssembly的支持,且执行速度相差无几。

为了理解与JavaScript相比WebAssembly的执行速度有多快,应该首先阅读关于JavaScript引擎如何工作的文章。

让我们快速浏览下 V8 的运行机制:

JavaScript是如何工作的:与WebAssembly比较及其使用场景

在左边,是一些JavaScript源代码,包含JavaScript函数。首先需要解析它,以便将所有字符串转换为标记并生成抽象语法树(AST)。AST 是JavaScript程序逻辑结构在内存中的表示形式。一旦生成了 AST,V8 直接进入到机器码阶段。其后遍历树,生成机器码,就得到了编译好的函数,在这个过程中是没有提高遍历速度的。

现在,让我们看看V8管道在下一阶段的工作:

JavaScript是如何工作的:与WebAssembly比较及其使用场景

现在有了V8 的新的优化编译器 (TurboFan), 当 JavaScript应用程序在运行时,很多代码都在 V8 中运行。TurboFan 监测是否有代码运行缓慢,是否存在性能瓶颈和热点(内存使用过高的地方),以便对其进行优化。它把以上监视得到的代码推向后端即优化过的即时编译器,该编译器把消耗大量 CPU 资源的函数转换为性能更优的代码。

它解决了性能的问题,但这种处理方式有个缺点,分析代码和决定优化哪些内容的过程也会消耗CPU,这意味着更高的耗电量,特别是在移动设备上

但是,wasm 并不需要以上的全部步骤-如下所示是它被插入到执行过程示意图:

JavaScript是如何工作的:与WebAssembly比较及其使用场景

在编译阶段,WebAssembly 不需要被转换,因为它已经是字节码了。总之,以上的解析不再需要,你拥有优化后的二进制代码可以直接插入到后端(即时编译器)并生成机器码。编译器在前端已经完成了所有的代码优化工作。

由于跳过了编译过程中的不少步骤,这使得 wasm 的执行更加高效。

WebAssembly 内存模型

JavaScript是如何工作的:与WebAssembly比较及其使用场景

例如,编译 成WebAssembly 的c++ 程序的内存是一个连续的内存块,其中没有“漏洞”。wasm 有助于提高安全性的一个特性是执行堆栈与线性内存分离的概念。在 c++ 程序中,如果有一个堆,从堆的底部进行分配,然后从其顶部获得内存来增加内存堆栈的大小。你可以获得一个指针然后在堆栈内存中遍历以操作你不应该接触到的变量。

这是大多数可疑软件可以利用的漏洞。

WebAssembly采用了完全不同的内在模式。执行堆栈与 WebAssembly 程序本身是分开的,因此无法在其中修改和更改诸如变量的值。同样,这些函数使用整数偏移量,而不是指针。函数指向一个间接函数表。之后,这些直接的计算出的数字进入模块中的函数。通过这种方式构建的,可以同时加载多个 wasm 模块,偏移所有索引且每个模块都运行良好。

更多关于 JavaScript 内存模型和管理的文章详见这里。

WebAssembly 垃圾收集

在 JavaScript 中,开发者不需要担心内存中无用变量的回收。JS 引擎使用一个叫垃圾回收器的东西来自动进行垃圾回收处理。

现在,WebAssembly 根本不支持垃圾回收。内存是手动管理的(就像 C/C++)。虽然这些可能让开发者编程更困难,但它的确提升了性能。

目前,WebAssembly 是专门围绕 C++ 和 RUST 的使用场景设计的。由于 wasm 是非常底层的语言,这意味着只比汇编语言高一级的编程语言会容易被编译成 WebAssembly。C 语言可以使用 malloc,C++ 可以使用智能指针,Rust 使用完全不同的模式(一个完全不同的话题)。这些语言没有使用内存垃圾回收器,所以他们不需要所有复杂运行时的东西来追踪内存。WebAssembly 自然就很适合于这些语言。

另外,这些语言并不能够 100% 地应用于复杂的 JavaScript 使用场景比如监听 DOM 变化 。用 C++ 来写整个的 HTML 程序是毫无意义的因为 C++ 并不是为此而设计的。大多数情况下,工程师用使用 C++ 或 Rust 来编写 WebGL 或者高度优化的库(比如大量的数学运算)。

然而,将来 WebAssembly 将会支持不带内存垃圾回功能的的语言。

WebAssembly 平台接口访问

依赖于执行 JavaScript 的运行时环境,对特定于平台的api的访问是公开的,可以通过 JavaScript 程序来直接访问这些平台所暴露出的指定接口。例如,如果您在浏览器中运行JavaScript,有一组Web API, Web 应用程序可以调用这些API来控制Web浏览器/设备功能,并访问 DOM、CSSOM、WebGL、IndexedDB、Web Audio API 等等。

然而,WebAssembly 模块不能访问任何平台api。所有的这一切都得由 JavaScript 来进行中转。如果想在 WebAssembly 模块中访问一些特定于平台的api,必须通过JavaScript调用它。

例如,如果想使用console.log,你必须通过JavaScript调用它,而不是C++代码。而这些 JavaScript 调用会产生一定的性能损失。

情况不会一成不变的。规范将会为在未来为 wasm 提供访问指定平台的接口,这样你就可以不用在你的程序中内置 JavaScript。

从源码转换讲起

JavaScript脚本正变得越来越复杂。大部分源码(尤其是各种函数库和框架)都要经过转换,才能投入生产环境。

常见的源码转换,主要是以下三种情况:

  1. 压缩,减小体积。比如jQuery 1.9的源码,压缩前是252KB,压缩后是32KB。
  2. 多个文件合并,减少HTTP请求数。
  3. 其他语言编译成JavaScript。最常见的例子就是CoffeeScript。

这三种情况,都使得实际运行的代码不同于开发代码,除错(debug)变得困难重重。如果你想提高Debug效率,欢迎免费试用Fundebug

通常,JavaScript的解释器会告诉你,第几行第几列代码出错。但是,这对于转换后的代码毫无用处。举例来说,jQuery 1.9压缩后只有3行,每行3万个字符,所有内部变量都改了名字。你看着报错信息,感到毫无头绪,根本不知道它所对应的原始位置。

这就是Source map想要解决的问题。

Source map

简单说,Source map就是一个信息文件,里面储存着位置信息。也就是说,转换后的代码的每一个位置,所对应的转换前的位置。有了它,出错的时候,除错工具将直接显示原始代码,而不是转换后的代码。这无疑给开发者带来了很大方便。

JavaScript是如何工作的:与WebAssembly比较及其使用场景

由于没有规范定义Source map,所以目前WebAssembly并不支持,但最终会有的(可能快了)。当你在 C++ 代码中设置了断点,你将会看到 C++ 代码而不是 WebAssembly。至少,这是 WebAssembly 源码映射的目标。

阅读Source Map入门教程,阔以了解更多细节。

多线程

JavaScript 是单线程的。有一些方法可以利用事件循环并利用异步编程,这个之前在 JavaScript是如何工作的:事件循环和异步编程的崛起+ 5种使用 async/await 更好地编码方式 已经讲过了。

JavaScript 也使用 Web Workers 但是只有在极其特殊的情况下-大体上,可以把任何可能阻塞 UI 主线程的密集的 CPU 计算移交给 Web Worker 执行以获得更好的性能。但是,Web Worker 不能够访问 DOM。

目前WebAssembly不支持多线程。但是,这有可能是接下来 WebAssembly 要实现的。Wasm 将会接近实现原生的线程(比如,C++ 风格的线程)。拥有真正的线程将会在浏览器中创造出很多新的机遇。并且当然,会增加滥用的可能性。

可移植性

现在JavaScript几乎可以在任何地方运行,从浏览器到服务器端,甚至在嵌入式系统中。

WebAssembly的设计宗旨是安全、便携。就像JavaScript。它将运行在每个支持 wasm 的环境中(例如,每个浏览器)。

WebAssembly 拥有和早年 Java 使用 Applets 来实现可移植性的同样的目标。

WebAssembly 使用场景

WebAssembly 的最初版本主要是为了解决大量计算密集型的计算的(比如处理数学问题)。最为主流的应用场景就是游戏——处理大量的像素。你可以使用你熟悉的 OpenGL 绑定来编写 C++/Rust 程序,然后编译成 wasm。之后,它就可以在浏览器中运行。

在浏览器中

  • 更好的让一些语言和工具可以编译到 Web 平台运行。
  • 图片/视频编辑。
  • 游戏:
    • 需要快速打开的小游戏
    • AAA 级,资源量很大的游戏。
    • 游戏门户(代理/原创游戏平台)
  • P2P 应用(游戏,实时合作编辑)
  • 音乐播放器(流媒体,缓存)
  • 图像识别
  • 视频直播
  • VR 和虚拟现实
  • CAD 软件
  • 科学可视化和仿真
  • 互动教育软件和新闻文章。
  • 模拟/仿真平台(ARC, DOSBox, QEMU, MAME, …)。
  • 语言编译器/虚拟机。
  • POSIX用户空间环境,允许移植现有的POSIX应用程序。
  • 开发者工具(编辑器,编译器,调试器...)
  • 远程桌面。
  • ×××。
  • 加密工具。
  • 本地 Web 服务器。
  • 使用 NPAPI 分发的插件,但受限于 Web 安全协议,可以使用 Web APIs。
  • 企业软件功能性客户端(比如:数据库)

脱离浏览器

  • 游戏分发服务(便携、安全)。
  • 服务端执行不可信任的代码。
  • 服务端应用。
  • 移动混合原生应用。
  • 多节点对称计算

原文:https://blog.sessionstack.com...

编辑中可能存在的bug没法实时知道,事后为了解决这些bug,花了大量的时间进行log 调试,这边顺便给大家推荐一个好用的BUG监控工具Fundebug。

你的点赞是我持续分享好东西的动力,欢迎点赞!

一个笨笨的码农,我的世界只能终身学习!

更多内容请关注公众号《大迁世界》!

关于Fundebug

Fundebug专注于JavaScript、微信小程序、微信小游戏、支付宝小程序、React Native、Node.js和Java实时BUG监控。 自从2016年双十一正式上线,Fundebug累计处理了9亿+错误事件,得到了Google、360、金山软件、百姓网等众多知名用户的认可。欢迎免费试用!

JavaScript是如何工作的:与WebAssembly比较及其使用场景

版权声明

转载时请注明作者Fundebug以及本文地址:
https://blog.fundebug.com/2018/12/24/how-does-webassembly-works/

转载于:https://blog.51cto.com/13957060/2334405

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.mzph.cn/news/388780.shtml

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

友元 java_C++ 友元关系详解

在C中,在某些情况下,允许特定的非成员函数访问一个类的私有成员,同时仍然阻止一般的访问,这是很方便做到的。例如,被重载的操作符,如输入或输出操作符,经常需要访问类的私有数据成员。这些操作符…

Matplotlib中的“ plt”和“ ax”到底是什么?

Indeed, as the most popular and fundamental data visualisation library, Matplotlib is kind of confusing in some perspectives. It is usually to see that someone asking about的确,作为最受欢迎的基础数据可视化库,Matplotlib在某些方面令人困…

【数据库的备份与还原】 .

差异备份,日志备份还原 IF DB_ID(db) IS NOT NULL DROP DATABASE db GO CREATE DATABASE db GO CREATE TABLE db.dbo.T(ID INT PRIMARY KEY IDENTITY(1,1)); GO BACKUP DATABASE db TO DISKd:/1.bak WITH FORMAT GO INSERT INTO db.dbo.T DEFAULT VALUES GO BACKUP DATAB…

方法 数组

方法的特点: 定义方法可以将功能代码进行封装 封装:两方面含义: 1.将有特定逻辑的多条代码组合成一个整体!! 2.方便维护,提高代码的复用性(联想变量的作用域问题) 方法只有被调用才会被执行!!(方法调用的流程) 方法的重载: 两同一不同: 同类,同方法名 形参列表不同 …

java 控制jsp_JSP学习之Java Web中的安全控制实例详解

普通用户界面修改登录的Servlet,修改后的代码如下:LoginProcess.java代码:package servlet;import javabean.User;import java.io.IOException;import java.io.PrintWriter;import javax.servlet.RequestDispatcher;import javax.servlet.Ser…

PHP 基础 自动类型转换之比较运算符

<?php var_dump( 123fg456>122); var_dump(some string 0); var_dump(123.0 123d456); var_dump(0 "a"); var_dump("1" "01"); var_dump("1" "1e0"); 当数字与字符串进行比较运算时&#xff0c;字符串会自动转…

java的多线程访问共享变量_java多线程通信之共享变量

(1)当访问共同的代码的时候&#xff1a;可以使用同一个Runnable对象&#xff0c;这个Runnable对象中有这个共享数据&#xff0c;比如卖票系统就可以这么做。或者这个共享数据封装在一个对象当中&#xff0c;然后对这个对象加锁&#xff0c;也可以实现数据安全访问。public clas…

2018年阿里云NoSQL数据库大事盘点

2019独角兽企业重金招聘Python工程师标准>>> NoSQL一词最早出现在1998年。2009年Last.fm的Johan Oskarsson发起了一次关于分布式开源数据库的讨论&#xff0c;来自Rackspace的Eric Evans再次提出了NoSQL概念&#xff0c;这时的NoSQL主要是指非关系型、分布式、不提供…

cayenne:用于随机模拟的Python包

TL;DR; We just released v1.0 of cayenne, our Python package for stochastic simulations! Read on to find out if you should model your system as a stochastic process, and why you should try out cayenne.TL; DR; 我们刚刚发布了 cayenne v1.0 &#xff0c;这是我们…

java 如何将word 转换为ftl_使用 freemarker导出word文档

近日需要将人员的基本信息导出&#xff0c;存储为word文档&#xff0c;查阅了很多资料&#xff0c;最后选择了使用freemarker&#xff0c;网上一共有四种方式&#xff0c;效果都一样&#xff0c;选择它呢是因为使用简单&#xff0c;再次记录一下,一个简单的demo&#xff0c;仅供…

DotNetBar office2007效果

1.DataGridView 格式化显示cell里的数据日期等。 进入编辑列&#xff0c;选择要设置的列&#xff0c;DefaultCellStyle里->行为->formart设置 2.tabstrip和mdi窗口的结合使用给MDI窗口加上TabPage。拖动个tabstrip到MDI窗口上tabstrip里选择到主窗口名就加上TABPAGE了。d…

Spring boot 中pom.xml 各个节点详解

<project xmlns"http://maven.apache.org/POM/4.0.0" xmlns:xsi"http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation"http://maven.apache.org/POM/4.0.0 http://maven.apache.org/maven-v4_0_0.xsd "> <!-- 父项目的坐…

spotify 数据分析_没有数据? 没问题! 如何从Wikipedia和Spotify收集重金属数据

spotify 数据分析For many data science students, collecting data is seen as a solved problem. It’s just there in Kaggle or UCI. However, that’s not how data is available daily for working Data Scientists. Also, many of the datasets used for learning have …

stack 的一些用法

#include<bits/stdc.h> using namespace std; int32_t main() {stack<int> st;st.push(1);st.push(2);st.push(3);cout<<st.size()<<endl;while(!st.empty()){cout<<st.top()<<endl;st.pop();} } 转载于:https://www.cnblogs.com/Andromed…

IS环境下配置PHP5+MySql+PHPMyAdmin

IIS环境下配置PHP5MySqlPHPMyAdmin Posted on 2009-08-07 15:18 谢启祥 阅读(1385)评论(18) 编辑 收藏 虽然主要是做.net开发的&#xff0c;但是&#xff0c;时不时的还要搞一下php&#xff0c;但是&#xff0c;php在windows下的配置&#xff0c;总是走很多弯路&#xff0c;正好…

js复制功能

<div id"cardList"><div class"btn" onClick"copy(111)">点击我&#xff0c;复制我</div></div> <script type"text/javascript"> function copy(str){var save function (e){e.clipboardData.setDa…

input在iOS里的兼容性

input框在iOS里&#xff0c;无法聚焦&#xff0c;不能输入内容&#xff0c;把-webkit-user-select:none改成-webkit-user-select:auto;或者直接加一个style“-webkit-user-select:auto”.

kaggle数据集_Kaggle上有170万份ArXiv文章的数据集

kaggle数据集“arXiv is a free distribution service and an open-access archive for 1.7 million scholarly articles in the fields of physics, mathematics, computer science, quantitative biology, quantitative finance, statistics, electrical engineering and sys…

java用接口实例化对象_[求助]迷茫中,接口可以直接实例化对象吗?

可能是我没有写完整吧,还是我没有理解好1 接口public interface SetAndGetWeight{public void setW(double weight);public double getW();}2 类class Train{SetAndGetWeight[] things;public void Train(SetAndGetWeight[] things){this.thingsthings;}public void returnTota…

异常作业2(2018.08.22)

2、编写程序接收用户输入分数信息&#xff0c;如果分数在0—100之间&#xff0c; 输出成绩。如果成绩不在该范围内&#xff0c; 抛出异常信息&#xff0c;提示分数必须在0—100之间。 要求&#xff1a;使用自定义异常实现1 import java.util.Scanner;2 3 class AtException ext…