├── screen.png ├── screen2.png ├── heap.js ├── index.html └── README.md /screen.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/justjavac/v8-javascript-memory/HEAD/screen.png -------------------------------------------------------------------------------- /screen2.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/justjavac/v8-javascript-memory/HEAD/screen2.png -------------------------------------------------------------------------------- /heap.js: -------------------------------------------------------------------------------- 1 | // d8 --allow_natives_syntax heap.js 2 | 3 | let s = Symbol(); 4 | %DebugPrint(s); 5 | 6 | let n = Object.create(null); 7 | %DebugPrint(n); 8 | 9 | let o = {}; 10 | %DebugPrint(o); 11 | -------------------------------------------------------------------------------- /index.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | v8-javascript-memory 7 | 8 | 9 | 10 | 18 | 19 | 20 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | # v8-javascript-memory 2 | 3 | V8 JavaScript 内存占用分析。 4 | 5 | > 回答知乎的问题:[v8 中 Symbol() 、Object.create(null) 和 {} 的内存占用分别是多少?](https://www.zhihu.com/question/425300093/answer/1523228095) 6 | 7 | ## 步骤 8 | 9 | 1. 使用 Chrome 浏览器访问 10 | 11 | 1. 打开 Dev Tools,如图: 12 | 13 | ![](./screen.png) 14 | 15 | 1. 选择 Memory 标签页 16 | 1. 点击 take heap snapshots 17 | 1. 在过滤框中输入 `ho` 快速过滤出 holder 18 | 19 | ## 名词解释 20 | 21 | **Shallow Size**:对象自身占用内存的大小,不包括它引用的对象。JavaScript 对象会将一些内存用于自身的说明和保存中间值。通常,只有数组和字符串会有明显的浅层大小。 22 | 23 | **Retained Size**:这是将对象本身连同其无法从 **GC root** 到达的相关对象一起删除后释放的内存大小。 24 | 25 | 单位是字节(Byte)。 26 | 27 | ## 分析 28 | 29 | 从截图中可以看到,`Symbol()` 的内存占用是 16。 30 | 31 | `Object.create(null)` 自身占用 12,总占用 88。 32 | 33 | `{}` 自身占用 28,总占用 28。 34 | 35 | 继续展开你会看到其他信息: 36 | 37 | ![](./screen2.png) 38 | 39 | 1. `__proto__` 是原型链。 40 | 2. `map` 就是很多文章都在介绍的 V8 对象的黑魔法 Hidden Class。 41 | 42 | ## 使用 V8 进行调试 43 | 44 | V8 的 `%DebugPrint()` 函数可以打印出对象的调试信息。这需要手动使用 `--is_debug=true` 参数来编译 V8。 45 | 46 | 代码: 47 | 48 | ```js 49 | let o = {}; 50 | %DebugPrint(o); 51 | ``` 52 | 53 | 运行:`d8 --allow_natives_syntax heap.js` 54 | 55 | 输出: 56 | 57 | ```plain 58 | DebugPrint: 0x2604080c60e9: [JS_OBJECT_TYPE] 59 | - map: 0x2604082802d9 [FastProperties] 60 | - prototype: 0x2604082413c9 61 | - elements: 0x2604080406e9 [HOLEY_ELEMENTS] 62 | - properties: 0x2604080406e9 {} 63 | 0x2604082802d9: [Map] 64 | - type: JS_OBJECT_TYPE 65 | - instance size: 28 66 | - inobject properties: 4 67 | - elements kind: HOLEY_ELEMENTS 68 | - unused property fields: 4 69 | - enum length: invalid 70 | - back pointer: 0x26040804030d 71 | - prototype_validity cell: 0x2604081c0451 72 | - instance descriptors (own) #0: 0x2604080401b5 73 | - prototype: 0x2604082413c9 74 | - constructor: 0x2604082413e5 75 | - dependent code: 0x2604080401ed 76 | - construction counter: 0 77 | ``` 78 | 79 | **注:** 虽然 node 和 deno 都支持 V8 的 `--allow_natives_syntax` 参数,但是如果你使用 node 或者 deno 运行,只能得到一行类似 `0x053bedbc1399 ` 的输出。 如果想得到详细的输出,必须手动编译,并且在编译过程中增加 `--is_debug=true` 参数。 80 | 81 | ## License 82 | 83 | 本作品justjavac 创作,采用知识共享署名-非商业性使用-相同方式共享 3.0 中国大陆许可协议进行许可。凡是转载的文章,翻译的文章,或者由其他作者投稿的文章,版权归原作者所有。 84 | --------------------------------------------------------------------------------