├── docs ├── find references from code.md ├── the mechanism of memory management in V8.md ├── the value type in V8.md ├── how to identify leaks.md ├── images │ ├── chapter1 │ │ ├── Crash.png │ │ ├── code.png │ │ ├── badend.png │ │ ├── devtools.png │ │ ├── toCode.png │ │ ├── memory status.png │ │ └── chrome inspect.png │ └── chapter2 │ │ ├── leak.png │ │ ├── bad code.png │ │ ├── memory line.png │ │ ├── memory scope.png │ │ ├── memory stack.png │ │ ├── memory inspect.png │ │ ├── memory line fixed.png │ │ ├── allocation timeline.png │ │ ├── memory dependencies.png │ │ └── memory stack details.png ├── how to prevent leaks.md ├── how to debug memory with Chrome Devtools.md ├── getting started.md ├── how to find memory leaks.md └── demo analyse.md ├── .gitignore ├── demo ├── simpleServer │ ├── package.json │ ├── server.js │ ├── server-lru.js │ └── package-lock.json └── vue leak │ ├── index.html │ └── index_fixed.html ├── README.md └── LICENSE.md /docs/find references from code.md: -------------------------------------------------------------------------------- 1 | -------------------------------------------------------------------------------- /.gitignore: -------------------------------------------------------------------------------- 1 | .idea/ 2 | node_modules/ 3 | .DS_Store -------------------------------------------------------------------------------- /docs/the mechanism of memory management in V8.md: -------------------------------------------------------------------------------- 1 | 1. 什么时候会消耗内存 2 | 2. 什么时候会触发内存回收 3 | 3. 长生态和老生态 -------------------------------------------------------------------------------- /docs/the value type in V8.md: -------------------------------------------------------------------------------- 1 | 1. 数值的类型 2 | 2. 数值在内存中是如何存储的? 3 | 3. 什么样的数据才是垃圾 4 | 4. 内存泄露背后的原因 -------------------------------------------------------------------------------- /docs/how to identify leaks.md: -------------------------------------------------------------------------------- 1 | 2 | 1. 应用内存使用是否过大? 3 | 2. 应用多久执行一次GC? 4 | 3. 是否内存一直随着时间而增长? -------------------------------------------------------------------------------- /docs/images/chapter1/Crash.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/andycall/master-of-javascript-memory/HEAD/docs/images/chapter1/Crash.png -------------------------------------------------------------------------------- /docs/images/chapter1/code.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/andycall/master-of-javascript-memory/HEAD/docs/images/chapter1/code.png -------------------------------------------------------------------------------- /docs/images/chapter2/leak.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/andycall/master-of-javascript-memory/HEAD/docs/images/chapter2/leak.png -------------------------------------------------------------------------------- /docs/images/chapter1/badend.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/andycall/master-of-javascript-memory/HEAD/docs/images/chapter1/badend.png -------------------------------------------------------------------------------- /docs/images/chapter1/devtools.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/andycall/master-of-javascript-memory/HEAD/docs/images/chapter1/devtools.png -------------------------------------------------------------------------------- /docs/images/chapter1/toCode.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/andycall/master-of-javascript-memory/HEAD/docs/images/chapter1/toCode.png -------------------------------------------------------------------------------- /docs/images/chapter2/bad code.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/andycall/master-of-javascript-memory/HEAD/docs/images/chapter2/bad code.png -------------------------------------------------------------------------------- /docs/images/chapter1/memory status.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/andycall/master-of-javascript-memory/HEAD/docs/images/chapter1/memory status.png -------------------------------------------------------------------------------- /docs/images/chapter2/memory line.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/andycall/master-of-javascript-memory/HEAD/docs/images/chapter2/memory line.png -------------------------------------------------------------------------------- /docs/images/chapter2/memory scope.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/andycall/master-of-javascript-memory/HEAD/docs/images/chapter2/memory scope.png -------------------------------------------------------------------------------- /docs/images/chapter2/memory stack.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/andycall/master-of-javascript-memory/HEAD/docs/images/chapter2/memory stack.png -------------------------------------------------------------------------------- /docs/images/chapter1/chrome inspect.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/andycall/master-of-javascript-memory/HEAD/docs/images/chapter1/chrome inspect.png -------------------------------------------------------------------------------- /docs/images/chapter2/memory inspect.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/andycall/master-of-javascript-memory/HEAD/docs/images/chapter2/memory inspect.png -------------------------------------------------------------------------------- /docs/images/chapter2/memory line fixed.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/andycall/master-of-javascript-memory/HEAD/docs/images/chapter2/memory line fixed.png -------------------------------------------------------------------------------- /docs/images/chapter2/allocation timeline.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/andycall/master-of-javascript-memory/HEAD/docs/images/chapter2/allocation timeline.png -------------------------------------------------------------------------------- /docs/images/chapter2/memory dependencies.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/andycall/master-of-javascript-memory/HEAD/docs/images/chapter2/memory dependencies.png -------------------------------------------------------------------------------- /docs/images/chapter2/memory stack details.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/andycall/master-of-javascript-memory/HEAD/docs/images/chapter2/memory stack details.png -------------------------------------------------------------------------------- /docs/how to prevent leaks.md: -------------------------------------------------------------------------------- 1 | 1. 删除DOM节点的时候,同时删除DOM元素的引用 2 | 2. 避免循环对象引用 3 | 3. 使用何时的作用域 4 | 4. 避免在异步代码中访问外部变量 5 | 5. 如果不需要了,就解除事件绑定 6 | 6. 使用合适的方式来管理缓存(lru-cache) -------------------------------------------------------------------------------- /docs/how to debug memory with Chrome Devtools.md: -------------------------------------------------------------------------------- 1 | 1. Performance工具 2 | 2. Memory工具 3 | 1. Heap snapshot (内存快哉) 4 | 2. 采用时间线来查看内存分配 5 | 3. 采用代码视角来查看内存分配 6 | 3. Chrome performance API 7 | 4. 调试Node.js内存 8 | -------------------------------------------------------------------------------- /demo/simpleServer/package.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "simpleserver", 3 | "version": "1.0.0", 4 | "description": "", 5 | "main": "request.js", 6 | "scripts": { 7 | "test": "echo \"Error: no test specified\" && exit 1", 8 | "start": "node server.js" 9 | }, 10 | "author": "", 11 | "license": "ISC", 12 | "dependencies": { 13 | "lru-cache": "^5.1.1", 14 | "uuid": "^3.3.2" 15 | } 16 | } 17 | -------------------------------------------------------------------------------- /docs/getting started.md: -------------------------------------------------------------------------------- 1 | # 前言 2 | 3 | 这是一本关于JavaScript内存管理的书,它所面向的读者是活跃在一线的中高级前端工程师。本书的内容将会是你分析内存泄露和优化页面性能的利器。 4 | 5 | 内存管理是每一位前端工程师在工作中都无法避开的一个话题,它既深不可测也十分强大。对于JavaScript而言,它既可以运行在浏览器上,也可以运行在服务器端,本书所包含的内容适合于任何运行JavaScript的平台,包括浏览器和Node.js。 6 | 7 | JavaScript是一门自带内存回收机制(Garbage Collection,英文简写GC)的编程语言,每一行JavaScript代码的背后都有编程语言默默为开发者完成变量内存的分配与回收。通常情况下,分配出去的内存都会被正确的回收回来。但是,当应用变得越来越复杂,代码量多到惊人的时候,代码中难免会出现一些问题,让分配出去的内存收不回来,如此反复下去,就会让应用所占用的内存不断增大,进而导致应用变慢,甚至是应用崩溃。 8 | 9 | 通过阅读本书,你将学会如何判定应用发生了内存泄露,以及如何在开发的过程中避免发生内存泄露,和使用适当的工具来找出问题的具体原因。 -------------------------------------------------------------------------------- /demo/simpleServer/server.js: -------------------------------------------------------------------------------- 1 | const http = require('http'); 2 | const uuid = require('uuid'); 3 | 4 | function readDataFromDataBase() { 5 | let cache = {}; 6 | return function(key) { 7 | if (cache[key]) { 8 | return cache[key]; 9 | } 10 | 11 | let data = new Array(10000).fill('xxxx'); 12 | cache[key] = data; 13 | return data; 14 | }; 15 | } 16 | 17 | const cachedDataBase = readDataFromDataBase(); 18 | 19 | const server = http.createServer((req, res) => { 20 | let key = uuid(); 21 | let data = cachedDataBase(key); 22 | res.end(JSON.stringify({ 23 | data: data 24 | })); 25 | }); 26 | 27 | server.listen(3000); 28 | console.log('Server listening to port 3000. Press Ctrl+C to stop it.'); -------------------------------------------------------------------------------- /demo/simpleServer/server-lru.js: -------------------------------------------------------------------------------- 1 | const http = require('http'); 2 | const uuid = require('uuid'); 3 | const LRU = require('lru-cache'); 4 | 5 | function readDataFromDataBase() { 6 | let cache = new LRU({ 7 | max: 50 8 | }); 9 | 10 | return function(key) { 11 | if (cache.has(key)) { 12 | return cache.get(key); 13 | } 14 | 15 | let data = new Array(10000).fill('xxxx'); 16 | cache.set(key, data); 17 | return data; 18 | }; 19 | } 20 | 21 | const cachedDataBase = readDataFromDataBase(); 22 | 23 | const server = http.createServer((req, res) => { 24 | let key = uuid(); 25 | let data = cachedDataBase(key); 26 | res.end(JSON.stringify({ 27 | data: data 28 | })); 29 | }); 30 | 31 | server.listen(3000); 32 | console.log('Server listening to port 3000. Press Ctrl+C to stop it.'); -------------------------------------------------------------------------------- /demo/simpleServer/package-lock.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "simpleserver", 3 | "version": "1.0.0", 4 | "lockfileVersion": 1, 5 | "requires": true, 6 | "dependencies": { 7 | "lru-cache": { 8 | "version": "5.1.1", 9 | "resolved": "https://registry.npmjs.org/lru-cache/-/lru-cache-5.1.1.tgz", 10 | "integrity": "sha512-KpNARQA3Iwv+jTA0utUVVbrh+Jlrr1Fv0e56GGzAFOXN7dk/FviaDW8LHmK52DlcH4WP2n6gI8vN1aesBFgo9w==", 11 | "requires": { 12 | "yallist": "^3.0.2" 13 | } 14 | }, 15 | "uuid": { 16 | "version": "3.3.2", 17 | "resolved": "https://registry.npmjs.org/uuid/-/uuid-3.3.2.tgz", 18 | "integrity": "sha512-yXJmeNaw3DnnKAOKJE51sL/ZaYfWJRl1pK9dr19YFCu0ObS231AB1/LbqTKRAQ5kw8A90rA6fr4riOUpTZvQZA==" 19 | }, 20 | "yallist": { 21 | "version": "3.0.3", 22 | "resolved": "https://registry.npmjs.org/yallist/-/yallist-3.0.3.tgz", 23 | "integrity": "sha512-S+Zk8DEWE6oKpV+vI3qWkaK+jSbIK86pCwe2IF/xwIpQ8jEuxpw9NyaGjmp9+BoJv5FV2piqCDcoCtStppiq2A==" 24 | } 25 | } 26 | } 27 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | # JavaScript 内存调试技巧与泄露分析 2 | 3 | 内存管理机制是写出高性能应用程序的必备技能,本书将介绍内存对应用带来的影响以及理解内存背后的机制,让读者学会如何分析内存,调试内存,让内存不再是应用开发中的一个黑盒。 4 | 5 | ## 前言 6 | 这是一本关于JavaScript内存的书,它所面向的读者是活跃在一线的中高级前端工程师。本书的内容将会是你分析内存泄露和优化页面性能的利器。 7 | 8 | 9 | ## 目录 10 | 11 | 1. [前言](./docs/getting%20started.md) 12 | 2. [实例分析:一个内存泄露的demo](./docs/demo%20analyse.md) 13 | 3. [如何发现内存泄露](./docs/how%20to%20find%20memory%20leaks.md) 14 | 4. [如何定位内存泄露](./docs/how%20to%20identify%20leaks.md) 15 | 5. [如何从代码中找出引用关系](./docs/find%20references%20from%20code.md) 16 | 6. [避免内存泄露的技巧](./docs/how%20to%20prevent%20leaks.md) 17 | 7. [V8内存管理基础](./docs/the%20value%20type%20in%20V8.md) 18 | 8. [V8内存管理机制](./docs/the%20mechanism%20of%20memory%20management%20in%20V8.md) 19 | 9. [使用Chrome DevTools 来调试内存](./docs/how%20to%20debug%20memory%20with%20Chrome%20Devtools.md) 20 | 21 | ## 版权许可 22 | 本书采用“保持署名—非商用”创意共享4.0许可证。 23 | 24 | 只要保持原作者署名和非商用,您可以自由地阅读、分享、修改本书。 25 | 26 | 详细的法律条文请参见创意共享网站。 27 | 28 | ## 关于作者 29 | 30 | 我是董天成,是一名活跃在一线开发的前端工程师,目前就职于百度。除了写本书之外,我还在专注一款新式前端应用框架的研发——[RCRE](https://github.com/andycall/RCRE)。 31 | 32 | github: https://github.com/andycall 33 | 34 | zhihu: https://www.zhihu.com/people/dong-tian-cheng/activities -------------------------------------------------------------------------------- /LICENSE.md: -------------------------------------------------------------------------------- 1 | 2 | # Creative Commons Attribution-NonCommercial 4.0 International License 3 | 4 | Disclaimer: This is a human-readable summary of (and not a substitute for) the [license](http://creativecommons.org/licenses/by-nc/4.0/legalcode). 5 | 6 | You are free to: 7 | 8 | - Share — copy and redistribute the material in any medium or format 9 | - Adapt — remix, transform, and build upon the material 10 | 11 | The licensor cannot revoke these freedoms as long as you follow the license terms. 12 | 13 | Under the following terms: 14 | 15 | - Attribution — You must give appropriate credit, provide a link to the license, and indicate if changes were made. You may do so in any reasonable manner, but not in any way that suggests the licensor endorses you or your use. 16 | - NonCommercial — You may not use the material for commercial purposes. 17 | - No additional restrictions — You may not apply legal terms or technological measures that legally restrict others from doing anything the license permits. 18 | 19 | Notices: 20 | 21 | You do not have to comply with the license for elements of the material in the public domain or where your use is permitted by an applicable exception or limitation. 22 | 23 | No warranties are given. The license may not give you all of the permissions necessary for your intended use. For example, other rights such as publicity, privacy, or moral rights may limit how you use the material. 24 | -------------------------------------------------------------------------------- /demo/vue leak/index.html: -------------------------------------------------------------------------------- 1 | 2 | 3 |
4 | 5 | 7 | 8 |
16 |
16 |
the window width: {{width}}px
76 |the window height: {{height}}px
77 |the window width: {{width}}px
106 |the window height: {{height}}px
107 |