JavaScript與WebAssembly進行比較

来源:https://www.cnblogs.com/qcloud1001/archive/2019/02/18/10394744.html
-Advertisement-
Play Games

本文由雲+社區發表 作者:QQ音樂前端團隊 在識別和描述核心元素的過程中,我們分享了構建SessionStack時使用的一些經驗法則,這是一個輕量級但健壯且高性能的JavaScript應用程式,以幫助用戶實時查看和重現其Web應用程式的缺陷。 這次我們來分析WebAssembly的工作原理,以及在如 ...


本文由雲+社區發表

作者:QQ音樂前端團隊

在識別和描述核心元素的過程中,我們分享了構建SessionStack時使用的一些經驗法則,這是一個輕量級但健壯且高性能的JavaScript應用程式,以幫助用戶實時查看和重現其Web應用程式的缺陷。

這次我們來分析WebAssembly的工作原理,以及在如下幾個方面和JavaScript進行比較:載入時間,執行速度,垃圾回收,記憶體使用情況,平臺API訪問,調試,多線程和可移植性。

WebAssembly的功能

WebAssembly(又名wasm)是一種高效的,低級別的編程語言。 它讓我們能夠使用JavaScript以外的語言(例如C,C ++,Rust或其他)編寫程式,然後將其編譯成WebAssembly,進而生成一個載入和執行速度非常快的Web應用程式。

載入時間

為了載入JavaScript,瀏覽器必須載入所有.js文本文件。 WebAssembly在瀏覽器中載入速度更快,因為只有已編譯的wasm文件才通過互聯網傳輸。並且wasm是一種非常簡潔的二進位格式的低級彙編語言,文件更小。

執行

目前Wasm 比本地代碼執行速度慢20%。這倒是一個令人吃驚的結果,不過,這是一種編譯到沙盒環境中的格式並且在很多約束條件下運行,以確保它沒有安全漏洞或者很難攻防這個漏洞。與真實的本地代碼相比,其實速度下降很小。但是,未來它會更快。

更好的是,它與瀏覽器無關 - 所有主要引擎都增加了對WebAssembly的支持,並且現在提供類似的執行時間。我們來看看簡單看看V8中發生了什麼:

img

V8 Approach: lazy compilation

在左邊,我們有一些JavaScript源代碼,包含JavaScript函數。它首先需要進行分析,以便將所有字元串轉換為標記並生成抽象語法樹(AST)。AST是JavaScript程式邏輯的記憶體表示。一旦生成這種表示,V8直接轉到機器碼。一般來說,只需要遍歷樹,生成機器代碼,便生成了編譯好的函數。從這個過程可以看出,這個階段並沒有編譯速度的優勢。 現在,我們來看看V8管道在下一階段的功能:

img

V8管道設計

這次我們有TurboFan,V8的優化編譯器之一。當您的JavaScript應用程式正在運行時,很多代碼在V8中運行。TurboFan可以監控運行緩慢的內容,是否存在瓶頸和熱點以優化它們。它將它們推送到後端,這是一個優化的JIT,它可以優化那些非常耗cpu的代碼。 雖然它解決了上述問題,但是新的問題在於:分析代碼並決定優化哪些內容的過程也會消耗CPU。這反過來又意味著更高的電池消耗,特別是在移動設備上。 然而,wasm不一樣在於,它會被插入工作流程中,如下所示:

img

記憶體模型

img

WebAssembly可信和不可信狀態 例如,編譯成WebAssembly的C ++程式的記憶體是連續的記憶體塊,其中沒有“漏洞”。有助於提高安全性的wasm的特性之一是執行堆棧與線性記憶體分離的概念。在一個C ++程式中,你有一個記憶體堆,你從堆的底部分配,然後從堆頂增漲堆大小。這便產生一個很多惡意軟體利用的漏洞:用一個指針就可以在堆棧記憶體中查找數據從而更改變數,而這些數據本是你不應該訪問到的。

WebAssembly採用完全不同的模型。執行堆棧與WebAssembly程式本身是分開的,因此您無法在其中修改並更改變數等內容。而且,這些函數使用整數偏移而不是指針。函數指向一個間接函數表。然後這些直接計算的數字跳轉到模塊內部的函數中。它是以這種方式構建的,以便您可以同時載入多個wasm模塊,形成多個索引列表,並且一切正常。 有關JavaScript中記憶體模型和管理的更多信息,可以查看關於該主題的非常詳細的帖子。

垃圾回收

您已經知道JavaScript的記憶體管理是使用垃圾回收器處理的。

WebAssembly的情況有點不同。它支持手動管理記憶體的語言。您可以自定義在WASM上的垃圾回收模塊,但是這個比較複雜。

目前,WebAssembly是圍繞C ++和RUST用例設計的。由於wasm是非常低級的,因此只有彙編語言上一步的編程語言才易於編譯。C可以使用普通的malloc,C ++可以使用智能指針,Rust使用完全不同的模式(完全不同的主題)。這些語言不使用GC,因此它們不需要所有複雜的運行時內容來跟蹤記憶體。WebAssembly對他們來說是天作之合。

另外,這些語言並不是100%設計用於調用複雜的JavaScript事物,如DOM。在C ++中編寫整個HTML應用程式是沒有意義的,因為C ++不是為它設計的。在大多數情況下,當工程師編寫C ++或Rust時,他們的目標是WebGL或高度優化的庫(例如重數學計算)。

但是,將來WebAssembly將支持不附帶GC的語言。

平臺API訪問

取決於執行JavaScript的運行時,可以通過你的JavaScript應用程式來訪問平臺相關的API。例如,如果您在瀏覽器中運行JavaScript,則您有一組Web APIs,Web應用程式可以調用它來控制Web瀏覽器/設備功能並訪問DOM, CSSOM, WebGL, IndexedDB, Web Audio API等。

然而,WebAssembly模塊無法訪問任何平臺API。一切都是由JavaScript調用的。如果您想訪問WebAssembly模塊中的某些平臺特定的API,則必須通過JavaScript調用它。

例如,如果你想console.log,你必須通過JavaScript來調用它,而不是你的C ++代碼。這些JavaScript調用的成本有所降低。

這並不總是如此。該規範將在未來為平臺API提供wasm,並且您將能夠在沒有JavaScript的情況下發佈您的應用程式。

Source maps

當您精簡JavaScript源代碼時,您需要一種正確方式調試它。這就需要Source Maps。基本上, Source Maps 是一種將組合/縮小文件映射回未建立狀態的方法。當您為生產而構建時,同時縮小和組合您的JavaScript文件,您將生成一個包含原始文件信息的源映射。當您在生成的JavaScript中查詢某一行和列號時,可以在返回原始位置的源地圖中執行查找。

WebAssembly目前不支持source maps,因為沒有規範,但最終會支持(可能很快)。 當您在C ++代碼中設置斷點時,您將看到C ++代碼而不是WebAssembly。

多線程

JavaScript在單個線程上運行。有很多方法可以利用Event Loop並利用非同步編程。

JavaScript也使用Web Workers,但他們有一個非常具體的用例 - 基本上,可能阻塞主UI線程的任何CPU密集計算都可以進入到Web Worker中來提高性能。但是,Web Workers無法訪問DOM。

WebAssembly目前不支持多線程。但是,這可能是未來的事情。Wasm將更接近本地線程(例如C ++樣式線程)。擁有“真實”的線程將在瀏覽器中創造出許多新的機會。當然,這將打開更多濫用可能性的大門。

可移植性

如今,JavaScript幾乎可以在任何地方運行,從瀏覽器到伺服器端甚至嵌入式系統。

WebAssembly被設計為安全和便攜。就像JavaScript一樣。它將運行在支持主機的每個環境中(例如每個瀏覽器)。就像當年的Java的Applets,WebAssembly有相同的可移植性的願景。

哪些場景更合適使用WA

在WebAssembly的第一個版本中,主要關註CPU占用大的計算(例如處理數學)。想到的最主流的用途是游戲 - 那裡有大量的像素操作。您可以使用您習慣的OpenGL在C ++ / Rust中編寫您的應用程式,並將其編譯為wasm。它會在瀏覽器中運行。 看看這個(在Firefox中運行)

http://s3.amazonaws.com/mozilla-games/tmp/2017-02-21-SunTemple/SunTemple.html

這是 Unreal engine.。

另一種使用WebAssembly(性能方面)可能有意義的情況是實現一些庫,這是一個CPU密集型工作。例如,一些圖像處理。

如前所述,由於大多數處理步驟都是在編譯期間提前完成的,因此wasm可以減少移動設備上的電池消耗(取決於引擎)。

將來,即使您實際上沒有編寫編譯代碼,您也可以使用WASM二進位文件。您可以在NPM中找到開始使用此方法的項目。

對於DOM操作和沉重的平臺API使用,使用JavaScript確實很有意義,因為它不會增加額外的開銷,並且具有本地提供的API。

在SessionStack中,我們不斷增強JavaScript的性能,以編寫高度優化且高效的代碼。我們的解決方案需要提供超快的性能,因為我們不能阻礙客戶應用的性能。將SessionStack集成到生產Web應用程式或網站後,它會開始記錄所有內容:所有DOM更改,用戶交互,JavaScript異常,堆棧跟蹤,失敗的網路請求和調試數據。所有這些都在您的生產環境中進行,而不會影響產品的任何UX和性能。我們需要大量優化我們的代碼並儘可能使其非同步。

不僅僅是庫文件,當在SessionStack中重放用戶回話時,我們會渲染用戶瀏覽器中發生的所有事件,並且我們必須重構整個狀態,允許您在會話時間線中來回跳轉。因為沒有更好的選擇,為了做到這一點,我們大量使用了JavaScript提供的非同步機會。

藉助WebAssembly,我們將能夠將一些最繁重的處理和渲染轉換為更適合作業的語言,並將數據收集和DOM操作保留為JavaScript。

如果你想嘗試下SessionStack,你可以免費開始。有一個免費的計劃),每月提供1000個會話。

img

參考:

此文已由騰訊雲+社區在各渠道發佈

獲取更多新鮮技術乾貨,可以關註我們騰訊雲技術社區-雲加社區官方號及知乎機構號


您的分享是我們最大的動力!

-Advertisement-
Play Games
更多相關文章
  • creat-react-app生成的項目預設埠號是3000,如下可以更改: next.js按文檔生成的項目預設也是3000 加 -p 埠號 即可。 ...
  • ECMAScript 中的相等操作符由兩個等於號 ( == ) 表示,如果兩個操作數相等,則返回 true。 相等操作符會先轉換操作數(通常稱為強制轉型),然後比較它們的相等性。 在轉換不同的數據類型時,相等操作符遵循下列基本規則: 1. 如果有一個操作數是布爾值,則在比較相等性之前,將其轉換為數值 ...
  • jQuery 簡介 選擇器 基本選擇器: $(" "), $(" id"), $(".class"), $("element"), $(".class,p,div") 層級選擇器: $(".outer div"), $(".outer div"), $(".outer+div"), $(".oute ...
  • 個人JS體系整理(一) 一. 原型 JS每聲明一個Function,都有Prototype原型,Prototype原型是函數的一個預設屬性,在函數的創建過程中由JS編譯器自動添加,也就是說每當生產一個Function對象的時候,就有一個原型Prototype。按照Javascript的說法,Func ...
  • 改變 HTML 樣式 如需改變 HTML 元素的樣式,請使用這個語法: 例子 下麵的例子會改變 <p> 元素的樣式: ...
  • 前言: 如果你是個前端開發人員,你肯定知道線上環境要把js,css,圖片等壓縮,儘量減少文件的大小,提升響應速度,特別是對移動端,這個非常重要。常用的前端性能優化方法有如下幾種 一、減少http請求 二、CSS Sprites 三、使用CDN加速 四 、css,js代碼壓縮 五、將樣式表放在頭部,將 ...
  • 前端工程本質上是軟體工程的一種。軟體工程化關註的是性能、穩定性、可用性、可維護性等方面,註重基本的開發效率、運行效率的同時,思考維護效率。一切以這些為目標的工作都是"前端工程化"。工程化是一種思想而不是某種技術。 本篇文章你可以學到: 如何使小程式支持scss; 怎樣通過gulp編譯你的項目; 項目 ...
  • 由於博客雲後臺管理工具寫起東西來實在難受,所以直接共用源碼了! https://pan.baidu.com/s/1XeRxlk7iv5qt1f16s64F9w H5源碼!暫時只支持手機適配,電腦端需要後續優化! https://pan.baidu.com/s/1eNOWb0wgIbloPzzqE0a ...
一周排行
    -Advertisement-
    Play Games
  • 移動開發(一):使用.NET MAUI開發第一個安卓APP 對於工作多年的C#程式員來說,近來想嘗試開發一款安卓APP,考慮了很久最終選擇使用.NET MAUI這個微軟官方的框架來嘗試體驗開發安卓APP,畢竟是使用Visual Studio開發工具,使用起來也比較的順手,結合微軟官方的教程進行了安卓 ...
  • 前言 QuestPDF 是一個開源 .NET 庫,用於生成 PDF 文檔。使用了C# Fluent API方式可簡化開發、減少錯誤並提高工作效率。利用它可以輕鬆生成 PDF 報告、發票、導出文件等。 項目介紹 QuestPDF 是一個革命性的開源 .NET 庫,它徹底改變了我們生成 PDF 文檔的方 ...
  • 項目地址 項目後端地址: https://github.com/ZyPLJ/ZYTteeHole 項目前端頁面地址: ZyPLJ/TreeHoleVue (github.com) https://github.com/ZyPLJ/TreeHoleVue 目前項目測試訪問地址: http://tree ...
  • 話不多說,直接開乾 一.下載 1.官方鏈接下載: https://www.microsoft.com/zh-cn/sql-server/sql-server-downloads 2.在下載目錄中找到下麵這個小的安裝包 SQL2022-SSEI-Dev.exe,運行開始下載SQL server; 二. ...
  • 前言 隨著物聯網(IoT)技術的迅猛發展,MQTT(消息隊列遙測傳輸)協議憑藉其輕量級和高效性,已成為眾多物聯網應用的首選通信標準。 MQTTnet 作為一個高性能的 .NET 開源庫,為 .NET 平臺上的 MQTT 客戶端與伺服器開發提供了強大的支持。 本文將全面介紹 MQTTnet 的核心功能 ...
  • Serilog支持多種接收器用於日誌存儲,增強器用於添加屬性,LogContext管理動態屬性,支持多種輸出格式包括純文本、JSON及ExpressionTemplate。還提供了自定義格式化選項,適用於不同需求。 ...
  • 目錄簡介獲取 HTML 文檔解析 HTML 文檔測試參考文章 簡介 動態內容網站使用 JavaScript 腳本動態檢索和渲染數據,爬取信息時需要模擬瀏覽器行為,否則獲取到的源碼基本是空的。 本文使用的爬取步驟如下: 使用 Selenium 獲取渲染後的 HTML 文檔 使用 HtmlAgility ...
  • 1.前言 什麼是熱更新 游戲或者軟體更新時,無需重新下載客戶端進行安裝,而是在應用程式啟動的情況下,在內部進行資源或者代碼更新 Unity目前常用熱更新解決方案 HybridCLR,Xlua,ILRuntime等 Unity目前常用資源管理解決方案 AssetBundles,Addressable, ...
  • 本文章主要是在C# ASP.NET Core Web API框架實現向手機發送驗證碼簡訊功能。這裡我選擇是一個互億無線簡訊驗證碼平臺,其實像阿裡雲,騰訊雲上面也可以。 首先我們先去 互億無線 https://www.ihuyi.com/api/sms.html 去註冊一個賬號 註冊完成賬號後,它會送 ...
  • 通過以下方式可以高效,並保證數據同步的可靠性 1.API設計 使用RESTful設計,確保API端點明確,並使用適當的HTTP方法(如POST用於創建,PUT用於更新)。 設計清晰的請求和響應模型,以確保客戶端能夠理解預期格式。 2.數據驗證 在伺服器端進行嚴格的數據驗證,確保接收到的數據符合預期格 ...