# Memory [notion 連結](https://marred-zinc-217.notion.site/Memory-03554bc767c54ab0b55339da884280bf) # 目錄 - **[Memory](https://www.notion.so/Memory-03554bc767c54ab0b55339da884280bf)** - **[Memory management](https://www.notion.so/Memory-03554bc767c54ab0b55339da884280bf)** - **[Memory life cycle](https://www.notion.so/Memory-03554bc767c54ab0b55339da884280bf)** - **[Memory Heap](https://www.notion.so/Memory-03554bc767c54ab0b55339da884280bf)** - [Chrome DevTools Memory](https://www.notion.so/Memory-03554bc767c54ab0b55339da884280bf) - **[Memory terminology](https://www.notion.so/Memory-03554bc767c54ab0b55339da884280bf)** # 參考資料 [Memory terminology - Chrome Developers](https://developer.chrome.com/docs/devtools/memory-problems/memory-101/) [Memory management - JavaScript | MDN](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Memory_Management) [身為 JS 開發者,你應該要知道的記憶體管理機制](https://medium.com/starbugs/身為-js-開發者-你不能不知道的記憶體管理機制-d9db2fd66f8) [How JavaScript works: memory management + how to handle 4 common memory leaks](https://blog.sessionstack.com/how-javascript-works-memory-management-how-to-handle-4-common-memory-leaks-3f28b94cfbec) [The story of a V8 performance cliff in React](https://v8.dev/blog/react-cliff) [深度解析!JavaScript中变量存储在堆中还是栈中?](https://mp.weixin.qq.com/s?__biz=MzkxMjI3MTA1Mg%3D%3D&mid=2247508506&idx=1&sn=2a376ee6f6a5a6d0b874f826ca659bab&fbclid=IwAR2KtHfvfrJ9kg3liW_OB0S7H9OfLIyiaWM46-l689Oq8Nrqj-5IkKHCsoo) ## **Memory** --- ### **Memory management 記憶體管理** 像是 C/C++ 較低階的語言, 工程師會需要透過記憶體控管 malloc(), free(), 自行確保所分配的 memory 被正確地釋放, 不然有可能會造成記憶體洩漏(Memory Leak)。 而大部分比較高階的程式語言 (Javascript) 都具有垃圾回收機制 (Garbage Collection), 簡單來說是**自動釋放不再使用的空間。** <aside> ⚠️ 因為有了自動垃圾回收機制,常常會使開發者產生可以不須理會「記憶體管理」的錯誤認知。 </aside> ### **Memory life cycle 記憶體生命週期** ![](https://i.imgur.com/CHTbWX4.png) 不論是哪種程式語言,記憶體生命週期(運作方式)幾乎總是一樣: 1. 配置你程式需要的記憶體空間 2. 使用配置到的記憶體空間(讀,寫) 3. 當不再使用時釋放已被配置的記憶體空間 ## **Memory Heap** ![](https://i.imgur.com/In9y4Rh.png) ### Are JavaScript primitive types stored on the heap or on the stack? ![](https://i.imgur.com/uaE4AFO.png) 假如一個是一個容量非常大的string, 那他還是存在於 stack 嗎? ### 不同的說法 1. primitive是直接存在stack裡面的,也是網路上比較多的文章寫的,也是我自己之前認為的。 ![](https://i.imgur.com/ckRedW3.png) 2. 不管是primitive或是object皆儲存在heap記憶體中。 而stack會保存heap裡面變數的ref,primitive跟object的差別在於,primitive會在heap create一個新的,然後將新的ref傳出去,而object不會,只會將現有的ref傳出去。最後,js會自動分辨型別,決定拿到的ref是 primitive還是object。 ![](https://i.imgur.com/eB6pID3.png) 其實 Strings 和 Numbers 並不完全都是存在 stack 或 heap。 - Strings v8 內部有一個名為 stringTable 的 hashmap緩存了所有字符串,在V8閱讀我們的代碼,轉換抽象語法樹時,每遇到一個字符串,會根據其特徵換算為一個 hash 值,插入到hashmap中。在之後如果遇到了hash值一致的字符串,會優先從裡面取出來進行比對,一致的話就不會生成新字符串類。(缓存字符串时,根据字符串不同采取不同 hash 方式) ```jsx // 證明:字串一樣, 在 heap 會指向同一個記憶體位址 const SolConstruction = function () { this.myString = 'IAmString' this.myString2 = 'IAmString' } var solConstructionA = new SolConstruction() ``` ```jsx // ---- 2 // 證明 1:改變字內容後,在 heap 的字串記憶體位址會改變 // 證明 2:當改變回原本的,在 heap 的字串記憶體位址又會復原 const SolConstruction = function () { this.myString = 'IAmString' this.myString2 = 'IAmString' } var solConstructionA = new SolConstruction() document.getElementById('try1').addEventListener('click',(e)=>{ solConstructionA.myString = '123' }) document.getElementById('try2').addEventListener('click',(e)=>{ solConstructionA.myString = 'IAmString' }) ``` - Numbers 數字在V8中分為 - Smi: For small integers in the 31-bit signed integer range, V8 uses a special representation called `Smi.` V8 is specifically optimized for `Smi`s, because small integers are so common in real-world JavaScript programs. `Smi`s don’t need to be allocated as dedicated entities in memory, and enable fast integer operations in general. - heapNumber 存在 heap 中, Smi 以外的都是這個 ```jsx -Infinity // HeapNumber -(2**30)-1 // HeapNumber -(2**30) // Smi -42 // Smi -0 // HeapNumber 0 // Smi 4.2 // HeapNumber 42 // Smi 2**30-1 // Smi 2**30 // HeapNumber Infinity // HeapNumber NaN // HeapNumber ``` ```jsx // ---- 3 // 證明: 小整數不會存在 heap const SolConstruction = function () { this.myNumber = 1 this.myNumber2 = 2 } var solConstructionA = new SolConstruction() document.getElementById('try1').addEventListener('click',(e)=>{ solConstructionA.myNumber2 = 3 }) document.getElementById('try2').addEventListener('click',(e)=>{ solConstructionA.myNumber2 = 2 }) ``` ```jsx // ---- 4 // 證明: 除了小整數以外都存在 heap const SolConstruction = function () { this.myNumber = 13.14 this.myNumber2 = 13.14 } var solConstructionA = new SolConstruction() document.getElementById('try1').addEventListener('click',(e)=>{ solConstructionA.myNumber2 = 13.14 }) document.getElementById('try2').addEventListener('click',(e)=>{ solConstructionA.myNumber2 = 13.14 }) ``` ### 結論: JS 在 V8 引擎中 - **string**: 存在 Heap 裡,且 V8 會 maintain 一個字串的 hashmap,如果是相同字串,就會引用相同的記憶體位置。 - **number**: 某些類型例如 smallint 會存在 Stack 中,其他類型則存在 Heap 裡。 <aside> 💖 In any case, for the JS programmer, worrying about stacks and heaps is somewhere between meaningless and distracting. It's more important to understand the behavior of various types of values. </aside> ## Chrome DevTools Memory ![](https://i.imgur.com/mcCtyMu.png) ## **Memory terminology** ### **Object sizes** An object can hold memory in two ways: - Directly by the object itself. ```jsx const a = { key:'haha'} ``` - Implicitly by holding references to other objects, and therefore preventing those objects from being automatically disposed by a garbage collector (**GC** for short). ```jsx const a = { key:'haha'}; const b = a; ``` - Shallow Size **物件本身佔用的記憶體量(bytes**),通常 shallow size 很大的都是 String 或是裝著 Primitive Type Data 的陣列,如果是物件裡存著 reference 則不會被算到 shallow size 裡面。 - Retained Size 物件本身佔用的記憶體空間,加上依賴此物件的所有資料所佔用的記憶體量(bytes)。文件裡有一句淺顯易懂的解釋:**你刪除這個物件後,他總共會釋放的記憶體量**,因此在查找 memory leak 問題時,我們會以這個為準。 - Distance the number of property references on the shortest retaining path from the window(global object). - **Objects retaining tree** The heap is a network of interconnected objects. In the mathematical world, this structure is called a graph or memory graph. A graph is constructed from nodes connected by means of edges, both of which are given labels. ![](https://i.imgur.com/eb7OxoL.png) # 補充 to be continue… [Debugging memory leaks - HTTP 203](https://www.youtube.com/watch?v=YDU_3WdfkxA&t=1s) [Fix memory problems - Chrome Developers](https://developer.chrome.com/docs/devtools/memory-problems/#overview)