「譯」內存管理碰撞課程

做者:Lin Clark
譯者:Cody Chan
原帖連接:A crash course in memory management

這是圖解 SharedArrayBuffers 系列的第一篇:web

  1. 內存管理碰撞課程segmentfault

  2. 圖解 ArrayBuffers 和 SharedArrayBuffers安全

  3. 用 Atomics 避免 SharedArrayBuffers 競爭條件函數

爲了更好地理解 JavaScript 裏的 ArrayBuffer 和 SharedArrayBuffer,首先應該瞭解點內存管理知識工具

你能夠把一個機器的內存想成一個一個的盒子,我把它們看成辦公室的郵箱或者幼兒園裏放小孩東西的格子性能

若是你想把某個東西留給某個小孩,你就把東西放到格子裏編碼

每一個盒子旁邊都有一個編號,這就是內存地址,用於告訴別人如何去找到你留的東西spa

每一個盒子大小都同樣,能夠存放特定容量東西。盒子的具體容量取決於機器,這個大小咱們稱爲字長,通常爲 32 位或者 64 位。不過,爲了展現方便,我這裏字長用 8 位翻譯

若是你想把數字 2 放到盒子裏,這很容易作到,由於數字很容易用二進制表示3d

可是若是你想放一個非數字類型的呢?好比字母 H?

咱們須要一種方式能夠用數字來表示它,這須要藉助編碼技術,相似 UTF-8 。首先,咱們須要一個東西能夠把字母轉爲數字……相似一個編碼環,接下來就能夠存儲了

當咱們從盒子裏取回的時候,咱們須要把取出的數字放到解碼環裏翻譯回字母 H

自動內存管理

若是你是寫 JavaScript 的,實際上你根本不須要關心內存,它對用戶是透明的,這意味着你沒法直接操縱內存

與此相對的, JS 引擎扮演着中間人角色,它爲你管理好內存

咱們用 React 舉個例子,好比建立一個變量

JS 引擎經過一個編碼器獲得這個變量的二進制表示

而後,它會找到內存中能夠放這個值的位置,這個過程稱爲內存分配

緊接着,引擎會持續追蹤這個變量,看其是否還在程序中被使用。若是這個變量已經沒有引用了,這塊內存會被回收,JS 引擎就又能夠在這裏放新的值了

追蹤內存中的變量(字符串、對象以及其它類型)而且在沒有引用的時候清除它們的過程咱們稱做垃圾回收

相似 JavaScript 這種代碼沒法直接處理內存的語言叫作自動內存管理(memory-managed)語言

內存自動管理確實讓開發者省了很多心,可是這也會帶來額外的開銷,這些額外開銷會讓程序的性能沒法評估

手動內存管理

手動內存管理的語言不太同樣,繼續上面例子,看 React 用 C 寫的話(藉助 WebAssembly可能的)會如何處理內存

不像 JavaScript,C 沒有單獨的內存管理抽象層,相反,你得直接與內存打交道。你能夠從內存中直接拿東西,也能夠直接往內存裏存東西

當你把 C 或者其它語言編譯爲 WebAssembly 時,編譯工具會在 WebAssembly 裏增長一些輔助代碼。好比,它會加入編解碼的代碼,這些代碼咱們稱爲運行時環境,運行時環境會幫助處理一些相似 JS 引擎幫 JS 作的事

可是,對於手動管理內存的語言,運行時不會包括垃圾回收

這並不意味着你須要徹底由本身處理內存,即便在這類語言裏,運行時你依然會獲得一些輔助。好比,C 語言運行時會在一個 free list 裏追蹤能夠使用的內存地址

你能夠使用 malloc 函數(內存分配的簡稱)向運行時發出能夠知足你數據存儲須要的內存請求,這些內存會被從 free list 拿下來。當你用完了,須要調用 free 去釋放內存,這些內存會被加回 free list

你必須清楚知道何時去調用這些函數,這就是爲何咱們叫手動內存管理

做爲一個開發者,知道何時去釋放什麼地方的內存是一件困難的事。若是你在錯誤時機處理了,這極可能會致使 BUG,甚至安全漏洞;若是你不處理,就會致使內存泄露

這就是爲何不少語言選擇自動內存管理去避免人爲錯誤,可是這犧牲了性能,下篇文章我還會談到這些

相關文章
相關標籤/搜索