摘要:因為有了類型猜測,引擎通常會比真實需要預留更多的空間。如果你是手動維護的內存,可以根據實際使用需求來決定分配和釋放內存的策略很多時候,這不是什么大不了的事。大多數場景并不會對性能要求那么苛刻,反而更多地擔心管理內存的麻煩。
這是圖解 SharedArrayBuffers 系列的第二篇:
內存管理碰撞課程
圖解 ArrayBuffers 和 SharedArrayBuffers
用 Atomics 避免 SharedArrayBuffers 競爭條件
上一篇文章中,我解釋了 JavaScript 這類自動管理內存的語言是如何處理內存的,同樣也解釋了類似 C 語言這種手動管理內存的語言
為什么這對于我們討論的 ArrayBuffers 和 SharedArrayBuffers 如此重要?
因為即使你使用的是 JavaScript 這種自動管理內存的語言,ArrayBuffers 也提供了一種手動處理數據的途徑
為什么你會有這樣的需求呢?
正如上篇文章所說,這里有個權衡,自動管理內存對開發者是友好的,但是這會增加機器負擔,甚至會有性能問題
例如,JS 里創建一個變量,引擎會去猜測變量的類型以及內存里如何表示。因為有了類型猜測,JS 引擎通常會比真實需要預留更多的空間。根據變量不同,內存分配可能會是真實需求的 2-8 倍,這導致了內存浪費
而且,某些創建和使用 JS 對象的場景會讓垃圾回收變得很困難。如果你是手動維護的內存,可以根據實際使用需求來決定分配和釋放內存的策略
很多時候,這不是什么大不了的事。大多數場景并不會對性能要求那么苛刻,反而更多地擔心管理內存的麻煩。而且一般情況下,手動管理內存可能更慢
但是對于底層需要極致優化的場景,ArrayBuffers 和 SharedArrayBuffers 為你提供了可能
ArrayBuffer 是如何工作的ArrayBuffer 跟其它 JavaScript 數組差不多,但是不是所有 JavaScript 類型都可以放進去,比如對象、字符串。你唯一可以放進去的只有字節(可以用數字表示)
需要澄清的一點是,你事實上不是直接把這個字節到 ArrayBuffer 里就行了,ArrayBuffer 并不知道字節有多長,該用多少位去存
ArrayBuffer 僅僅是一個個 0/1 組成的串,它不知道第一個元素和第二個元素的分割點
為了提供必要的上下文信息,把 ArrayBuffer 分塊,我們需要把它包裹到視圖里,這些數據的視圖可以通過帶類型的數組添加,已經支持很多種類型的數組了
例如,你可以用一個 Int8 類型的數組把 0/1 串分割成 8 位一組的序列
或者你可以用一個無符的 Int16 類型數組,把它分割成 16 位一組的序列,可以把它當作無符整型處理
甚至你可以在同一個基礎 buffer 上同時處理多種視圖,不同視圖在相同操作下會返回不同的結果
例如,如果我們從某個 ArrayBuffer 的 Int8 視圖得到第 0 和第 1 個元素的值,在 Uint16 視圖下,第 0 個元素與其有相同二進制位值,但是得到的值也會不一樣
這種方式下,ArrayBuffer 幾乎是扮演原始內存角色了,它模擬內存的各種跟 C 語言里類似的操作
你可能納悶了,為什么不讓開發者直接操縱內存而是采用這個抽象層。因為直接操作內存會有安全風險,這個以后的文章會講
什么是 SharedArrayBuffer為了說明白 SharedArrayBuffers,我需要稍微解釋下并行運行代碼和 JavaScript 的關系
為了更快運行代碼或者更更快響應用戶事件,你可能會讓代碼并行運行,為了做到這點,你需要分割工作
一個典型的應用中,所有的工作都由一個多帶帶的主線程處理,這點我之前提到過……這個主線程就像一個全棧工程師,掌管著 JavaScript、DOM 和 視圖
任何能夠從主線程負載減少工作的方法都對代碼運行效率有幫助,某些情況下,ArrayBuffers 可以減少大量應該由主線程做的工作
但是也有些時候減少主線程負載是遠遠不夠的,有時你需要增援,你需要分割你的任務
大多數語言里,這種分割工作的方法可以使用多線程實現,這就像很多人同時在一個項目里工作。如果你可以完美地把任務分割為多個獨立的部分,你可以分給不同的線程,然后,這些線程就同時各種獨立執行這些任務
在 JavaScript 里,你可以借助 web worker 做這種事,這些 web workers 跟其它語言的線程還是有些區別的,默認它們不能共享內存
這意味著如果你想分配你的任務給別的線程,你需要完整把任務復制過去,這可以通過 postMessage 實現
postMessage 把你傳給它的任何對象都序列化,發送到其它 web worker,然后那邊接收后反序列化并放進內存
這個過程是非常慢的
某些類型數據(如 ArrayBuffers)你可以通過移動內存的方式實現,這意味著把某個特定區域的內存移過去后其它 web worker 就可以直接訪問了
但是,之前的 web worker 就無法訪問了
對于某些場景這是實用的,但是也有很多場景對性能要求高,你只能使用共享的內存
而這就是 SharedArrayBuffers 為你提供的
有了 SharedArrayBuffer 后,多個 web worker 就可以同時讀寫同一塊內存了
你再也不需要 postMessage 伴有時延的通信了,多個 web worker 對數據訪問都沒有時延了
當然,這種同時訪問也有風險,會產生競爭條件
這個下一篇文章會細說
SharedArrayBuffers 支持情況所有主流瀏覽器都將會支持 SharedArrayBuffers
Safari 10.1 已經支持了,Firefox 和 Chrome 也會很快支持并發布,Edge 會在他們秋季 Windows 更新的時候發布
即使所有主流瀏覽器都支持了,我們也不希望開發者直接使用它們,事實上,我們是反對的。你應該只使用更高級的封裝好的抽象層接口
我們期盼的是 JavaScript 庫開發者可以提供更簡單安全的方法來使用 SharedArrayBuffers
而且,一旦 SharedArrayBuffers 內置到平臺中,WebAssembly 可以通過它實現多線程,到那時候你就可以使用類似 Rust 的多線程語言輕松玩轉多線程了
下一篇文章我們會介紹一個為避免競爭條件的庫提供基礎操作的工具(Atomics)
文章版權歸作者所有,未經允許請勿轉載,若此文章存在違規行為,您可以聯系管理員刪除。
轉載請注明本文地址:http://specialneedsforspecialkids.com/yun/83578.html
摘要:你可以從內存中直接拿東西,也可以直接往內存里存東西當你把或者其它語言編譯為時,編譯工具會在里增加一些輔助代碼。 作者:Lin Clark 譯者:Cody Chan 原帖鏈接:A crash course in memory management 這是圖解 SharedArrayBuffers 系列的第一篇: 內存管理碰撞課程 圖解 ArrayBuffers 和 SharedA...
摘要:如果期間有其它線程更新了,則會先拿到新的值重新運算一次多運算的競爭條件這些運算符成功避免了單運算中的競爭條件。 作者:Lin Clark 譯者:Cody Chan 原帖鏈接:Avoiding race conditions in SharedArrayBuffers with Atomics 這是圖解 SharedArrayBuffers 系列的第三篇: 內存管理碰撞課程 圖...
摘要:前端日報精選劉海打理指北中的錯誤處理模式與反模式譯圖解和譯你并不知道中文裝飾器讓你的代碼更簡潔眾成翻譯第期每個程序員第一份工作前應該知道的件事中的不變性眾成翻譯寫的一次小結掘金內部機制探秘和文末附彩蛋和源碼前端雜談開發實戰 2017-09-30 前端日報 精選 iPhone X 劉海打理指北React16中的錯誤處理ES6 Promise:模式與反模式「譯」圖解 ArrayBuffer...
摘要:前端日報精選十問幫你理清前端工程師及大前端團隊的成長問題譯讀完細則之后學到的件事掘金怎么寫一個組件庫一眾成翻譯還有這操作一個能生成思維導圖的開源搜索引擎知乎專欄中文前端推薦第天值得收藏的基礎教程知乎專欄第期沒有的一天轉載中回調地 2017-06-15 前端日報 精選 十問sofish:幫你理清前端工程師及大前端團隊的成長問題![譯] 讀完 flexbox 細則之后學到的 11 件事 -...
2017-10-01 前端日報 精選 網頁保存為圖片及高清截圖的優化方法前端最佳實踐(一)——DOM操作Vue 2.0學習筆記:v-bindReact Router v4 之代碼分割:從放棄到入門js實用的十個小技巧Netflix/falcor: A JavaScript library for efficient data fetchinglllyasviel/style2paints: ske...
閱讀 1106·2021-11-23 10:05
閱讀 1785·2021-11-12 10:36
閱讀 1853·2019-08-30 15:56
閱讀 1684·2019-08-29 12:32
閱讀 3043·2019-08-28 18:04
閱讀 3428·2019-08-26 12:17
閱讀 2502·2019-08-26 11:35
閱讀 1240·2019-08-23 15:11