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.pswp.cn/news/388780.shtml
繁體地址,請注明出處:http://hk.pswp.cn/news/388780.shtml
英文地址,請注明出處:http://en.pswp.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…