# 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 記憶體生命週期**

不論是哪種程式語言,記憶體生命週期(運作方式)幾乎總是一樣:
1. 配置你程式需要的記憶體空間
2. 使用配置到的記憶體空間(讀,寫)
3. 當不再使用時釋放已被配置的記憶體空間
## **Memory Heap**

### Are JavaScript primitive types stored on the heap or on the stack?

假如一個是一個容量非常大的string, 那他還是存在於 stack 嗎?
### 不同的說法
1. primitive是直接存在stack裡面的,也是網路上比較多的文章寫的,也是我自己之前認為的。

2. 不管是primitive或是object皆儲存在heap記憶體中。
而stack會保存heap裡面變數的ref,primitive跟object的差別在於,primitive會在heap create一個新的,然後將新的ref傳出去,而object不會,只會將現有的ref傳出去。最後,js會自動分辨型別,決定拿到的ref是 primitive還是object。

其實 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

## **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.

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