---
# System prepended metadata

title: Memory

---

# 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)