{"componentChunkName":"component---src-templates-post-template-js","path":"/posts/js-memory-leak","result":{"data":{"markdownRemark":{"id":"2440dd37-48c6-5785-89b7-3986b1a9de21","html":"<h2 id=\"故事\" style=\"position:relative;\"><a href=\"#%E6%95%85%E4%BA%8B\" aria-label=\"故事 permalink\" class=\"anchor before\"><svg aria-hidden=\"true\" focusable=\"false\" height=\"16\" version=\"1.1\" viewBox=\"0 0 16 16\" width=\"16\"><path fill-rule=\"evenodd\" d=\"M4 9h1v1H4c-1.5 0-3-1.69-3-3.5S2.55 3 4 3h4c1.45 0 3 1.69 3 3.5 0 1.41-.91 2.72-2 3.25V8.59c.58-.45 1-1.27 1-2.09C10 5.22 8.98 4 8 4H4c-.98 0-2 1.22-2 2.5S3 9 4 9zm9-3h-1v1h1c1 0 2 1.22 2 2.5S13.98 12 13 12H9c-.98 0-2-1.22-2-2.5 0-.83.42-1.64 1-2.09V6.25c-1.09.53-2 1.84-2 3.25C6 11.31 7.55 13 9 13h4c1.45 0 3-1.69 3-3.5S14.5 6 13 6z\"></path></svg></a>故事</h2>\n<ul>\n<li>跑 AIQUA UI unit testing 的時候，發生記憶體不足的問題</li>\n</ul>\n<div class=\"gatsby-highlight\" data-language=\"js\"><pre class=\"language-js\"><code class=\"language-js\"><span class=\"token constant\">FAIL</span> src<span class=\"token operator\">/</span><span class=\"token operator\">...</span><span class=\"token operator\">/</span>HtmlCreative<span class=\"token punctuation\">.</span>test<span class=\"token punctuation\">.</span>js\n  ● Test suite failed to run \n\n  <span class=\"token constant\">ENOMEM</span><span class=\"token operator\">:</span> not enough memory</code></pre></div>\n<ul>\n<li>CI 環境上有 6GB 的記憶體，真的不夠嗎？</li>\n</ul>\n<hr></hr>\n<h2 id=\"實驗與觀察\" style=\"position:relative;\"><a href=\"#%E5%AF%A6%E9%A9%97%E8%88%87%E8%A7%80%E5%AF%9F\" aria-label=\"實驗與觀察 permalink\" class=\"anchor before\"><svg aria-hidden=\"true\" focusable=\"false\" height=\"16\" version=\"1.1\" viewBox=\"0 0 16 16\" width=\"16\"><path fill-rule=\"evenodd\" d=\"M4 9h1v1H4c-1.5 0-3-1.69-3-3.5S2.55 3 4 3h4c1.45 0 3 1.69 3 3.5 0 1.41-.91 2.72-2 3.25V8.59c.58-.45 1-1.27 1-2.09C10 5.22 8.98 4 8 4H4c-.98 0-2 1.22-2 2.5S3 9 4 9zm9-3h-1v1h1c1 0 2 1.22 2 2.5S13.98 12 13 12H9c-.98 0-2-1.22-2-2.5 0-.83.42-1.64 1-2.09V6.25c-1.09.53-2 1.84-2 3.25C6 11.31 7.55 13 9 13h4c1.45 0 3-1.69 3-3.5S14.5 6 13 6z\"></path></svg></a>實驗與觀察</h2>\n<ul>\n<li>我們在用的是 Jest 這款 task runner</li>\n<li>它有提供兩個指令 <code class=\"language-text\">--runInBand</code> &#x26; <code class=\"language-text\">--logHeapUsage</code></li>\n<li><code class=\"language-text\">--runInBand</code>：只用一個 worker，一個測試跑完才跑下個測試</li>\n<li><code class=\"language-text\">--logHeapUsage</code>：輸出 heap memory 的使用量</li>\n</ul>\n<hr></hr>\n<h2 id=\"實驗結果\" style=\"position:relative;\"><a href=\"#%E5%AF%A6%E9%A9%97%E7%B5%90%E6%9E%9C\" aria-label=\"實驗結果 permalink\" class=\"anchor before\"><svg aria-hidden=\"true\" focusable=\"false\" height=\"16\" version=\"1.1\" viewBox=\"0 0 16 16\" width=\"16\"><path fill-rule=\"evenodd\" d=\"M4 9h1v1H4c-1.5 0-3-1.69-3-3.5S2.55 3 4 3h4c1.45 0 3 1.69 3 3.5 0 1.41-.91 2.72-2 3.25V8.59c.58-.45 1-1.27 1-2.09C10 5.22 8.98 4 8 4H4c-.98 0-2 1.22-2 2.5S3 9 4 9zm9-3h-1v1h1c1 0 2 1.22 2 2.5S13.98 12 13 12H9c-.98 0-2-1.22-2-2.5 0-.83.42-1.64 1-2.09V6.25c-1.09.53-2 1.84-2 3.25C6 11.31 7.55 13 9 13h4c1.45 0 3-1.69 3-3.5S14.5 6 13 6z\"></path></svg></a>實驗結果</h2>\n<div class=\"gatsby-highlight\" data-language=\"js\"><pre class=\"language-js\"><code class=\"language-js\"><span class=\"token constant\">PASS</span>  src<span class=\"token operator\">/</span><span class=\"token operator\">...</span><span class=\"token operator\">/</span>JourneyChart<span class=\"token punctuation\">.</span>test<span class=\"token punctuation\">.</span><span class=\"token function\">js</span> <span class=\"token punctuation\">(</span><span class=\"token number\">9.628</span>s<span class=\"token punctuation\">,</span> <span class=\"token number\">160</span> <span class=\"token constant\">MB</span> heap size<span class=\"token punctuation\">)</span>\n<span class=\"token constant\">PASS</span>  src<span class=\"token operator\">/</span><span class=\"token operator\">...</span><span class=\"token operator\">/</span>ReachMethodNode<span class=\"token punctuation\">.</span>test<span class=\"token punctuation\">.</span><span class=\"token function\">js</span> <span class=\"token punctuation\">(</span><span class=\"token number\">195</span> <span class=\"token constant\">MB</span> heap size<span class=\"token punctuation\">)</span>\n<span class=\"token operator\">...</span>\n<span class=\"token constant\">PASS</span>  src<span class=\"token operator\">/</span><span class=\"token operator\">...</span><span class=\"token operator\">/</span>validateGoalEvents<span class=\"token punctuation\">.</span>test<span class=\"token punctuation\">.</span><span class=\"token function\">js</span> <span class=\"token punctuation\">(</span><span class=\"token number\">2588</span> <span class=\"token constant\">MB</span> heap size<span class=\"token punctuation\">)</span>\n<span class=\"token constant\">PASS</span>  src<span class=\"token operator\">/</span><span class=\"token operator\">...</span><span class=\"token operator\">/</span>booleanString<span class=\"token punctuation\">.</span>test<span class=\"token punctuation\">.</span><span class=\"token function\">js</span> <span class=\"token punctuation\">(</span><span class=\"token number\">2603</span> <span class=\"token constant\">MB</span> heap size<span class=\"token punctuation\">)</span>\n<span class=\"token punctuation\">(</span>End<span class=\"token punctuation\">)</span></code></pre></div>\n<hr></hr>\n<p><img src=\"https://i.imgflip.com/4v8c5f.jpg\"> </p>\n<hr></hr>\n<h2 id=\"其他人也遇到了一樣的問題嗎？\" style=\"position:relative;\"><a href=\"#%E5%85%B6%E4%BB%96%E4%BA%BA%E4%B9%9F%E9%81%87%E5%88%B0%E4%BA%86%E4%B8%80%E6%A8%A3%E7%9A%84%E5%95%8F%E9%A1%8C%E5%97%8E%EF%BC%9F\" aria-label=\"其他人也遇到了一樣的問題嗎？ permalink\" class=\"anchor before\"><svg aria-hidden=\"true\" focusable=\"false\" height=\"16\" version=\"1.1\" viewBox=\"0 0 16 16\" width=\"16\"><path fill-rule=\"evenodd\" d=\"M4 9h1v1H4c-1.5 0-3-1.69-3-3.5S2.55 3 4 3h4c1.45 0 3 1.69 3 3.5 0 1.41-.91 2.72-2 3.25V8.59c.58-.45 1-1.27 1-2.09C10 5.22 8.98 4 8 4H4c-.98 0-2 1.22-2 2.5S3 9 4 9zm9-3h-1v1h1c1 0 2 1.22 2 2.5S13.98 12 13 12H9c-.98 0-2-1.22-2-2.5 0-.83.42-1.64 1-2.09V6.25c-1.09.53-2 1.84-2 3.25C6 11.31 7.55 13 9 13h4c1.45 0 3-1.69 3-3.5S14.5 6 13 6z\"></path></svg></a>其他人也遇到了一樣的問題嗎？</h2>\n<figure style=\"max-width: 600px; border: solid 2px rgb(200, 200, 200);\">\n\t<span class=\"gatsby-resp-image-wrapper\" style=\"position: relative; display: block; margin-left: auto; margin-right: auto; max-width: 960px; \">\n      <a class=\"gatsby-resp-image-link\" href=\"/static/c209dbd56a0a621acd9c86802ad68e1e/2093e/github-issue-1.png\" style=\"display: block\" target=\"_blank\" rel=\"noopener\">\n    <span class=\"gatsby-resp-image-background-image\" style=\"padding-bottom: 21.666666666666668%; position: relative; bottom: 0; left: 0; background-image: url(&apos;data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAABQAAAAECAYAAACOXx+WAAAACXBIWXMAAAsSAAALEgHS3X78AAAAzklEQVQY021Oy07EMBDr//8JVzhyRuLEQ0ICcaPdbmk32UzSpHk01ExGHLFk2Y6jxJ22GwadhD5VlH1HLjtrFc2cS6mwxmENG4x18CEw2ZMTbSTHvffoYilwPoAMwegrcspc8AW7YosJYYuIfOZWL7518gD3LRuy8jEOCLroIgIFWCJctQaxKlalmrfiL0qJJ16XcsZxHKi14udPG16XDzyMT+hu3+9x83yHcZzQDyecpwnDacRX32Pg/D3PmJeFl5AsK23NP3i7fOLx/IJftugxv6M4a5EAAAAASUVORK5CYII=&apos;); background-size: cover; display: block;\"></span>\n  <picture>\n        <source srcset=\"/static/c209dbd56a0a621acd9c86802ad68e1e/8ac56/github-issue-1.webp 240w,\n/static/c209dbd56a0a621acd9c86802ad68e1e/d3be9/github-issue-1.webp 480w,\n/static/c209dbd56a0a621acd9c86802ad68e1e/e46b2/github-issue-1.webp 960w,\n/static/c209dbd56a0a621acd9c86802ad68e1e/f992d/github-issue-1.webp 1440w,\n/static/c209dbd56a0a621acd9c86802ad68e1e/48a02/github-issue-1.webp 1858w\" sizes=\"(max-width: 960px) 100vw, 960px\" type=\"image/webp\">\n        <source srcset=\"/static/c209dbd56a0a621acd9c86802ad68e1e/8ff5a/github-issue-1.png 240w,\n/static/c209dbd56a0a621acd9c86802ad68e1e/e85cb/github-issue-1.png 480w,\n/static/c209dbd56a0a621acd9c86802ad68e1e/d9199/github-issue-1.png 960w,\n/static/c209dbd56a0a621acd9c86802ad68e1e/07a9c/github-issue-1.png 1440w,\n/static/c209dbd56a0a621acd9c86802ad68e1e/2093e/github-issue-1.png 1858w\" sizes=\"(max-width: 960px) 100vw, 960px\" type=\"image/png\">\n        <img class=\"gatsby-resp-image-image\" src=\"/static/c209dbd56a0a621acd9c86802ad68e1e/d9199/github-issue-1.png\" alt=\"&#x4F9D;&#x8CF4;&#x53CD;&#x8F49;&#x7BC4;&#x4F8B;&#x4E09;\" title=\"&#x4F9D;&#x8CF4;&#x53CD;&#x8F49;&#x7BC4;&#x4F8B;&#x4E09;\" loading=\"lazy\" style=\"width:100%;height:100%;margin:0;vertical-align:middle;position:absolute;top:0;left:0;\">\n      </picture>\n  </a>\n    </span>\n</figure>\n<figure style=\"max-width: 600px; border: solid 2px rgb(200, 200, 200);\">\n\t<span class=\"gatsby-resp-image-wrapper\" style=\"position: relative; display: block; margin-left: auto; margin-right: auto; max-width: 960px; \">\n      <a class=\"gatsby-resp-image-link\" href=\"/static/a1b1f474e4b1a1a26a65bb70a41dbf01/e0202/github-issue-2.png\" style=\"display: block\" target=\"_blank\" rel=\"noopener\">\n    <span class=\"gatsby-resp-image-background-image\" style=\"padding-bottom: 33.33333333333333%; position: relative; bottom: 0; left: 0; background-image: url(&apos;data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAABQAAAAHCAYAAAAIy204AAAACXBIWXMAAAsSAAALEgHS3X78AAABJ0lEQVQoz51Q7Y6CMBDk/V/v5EPB8yIoQimlrQjF6rhdYkwu9+s2WWaXbGdnNjocfqDNFUIqKG0wUC2V5v42OczLHbP7nQtkP9C85fmAxo643z2iVgj0RFBfWrSiQ9MKWmAxzQ6OyBYaYqRc+xVv08wzId+19w9EoCj234iTFLs8x9cmpgUK/4nn84kofEJorWEMWR40FBGKrkNQL/ueayk/2JKLnv6HWWMt4ziOK2Egm6aJFabZljBBXuyRZBmy7Y4zTlNs4oQcFEjSjFwk2O5ynOsal6ZBXV/gnGNhTOi9R1lWOFJWpzPKqsLpXDM2Tcsqg4orqVBUGz1ADwpdJ0kpuaHbu2X5EC7UhG2B4E0Y+uOxpPvu+WGwq4i0uz7QGA9h/Z83fAEowxVa7TnhYgAAAABJRU5ErkJggg==&apos;); background-size: cover; display: block;\"></span>\n  <picture>\n        <source srcset=\"/static/a1b1f474e4b1a1a26a65bb70a41dbf01/8ac56/github-issue-2.webp 240w,\n/static/a1b1f474e4b1a1a26a65bb70a41dbf01/d3be9/github-issue-2.webp 480w,\n/static/a1b1f474e4b1a1a26a65bb70a41dbf01/e46b2/github-issue-2.webp 960w,\n/static/a1b1f474e4b1a1a26a65bb70a41dbf01/79a63/github-issue-2.webp 1395w\" sizes=\"(max-width: 960px) 100vw, 960px\" type=\"image/webp\">\n        <source srcset=\"/static/a1b1f474e4b1a1a26a65bb70a41dbf01/8ff5a/github-issue-2.png 240w,\n/static/a1b1f474e4b1a1a26a65bb70a41dbf01/e85cb/github-issue-2.png 480w,\n/static/a1b1f474e4b1a1a26a65bb70a41dbf01/d9199/github-issue-2.png 960w,\n/static/a1b1f474e4b1a1a26a65bb70a41dbf01/e0202/github-issue-2.png 1395w\" sizes=\"(max-width: 960px) 100vw, 960px\" type=\"image/png\">\n        <img class=\"gatsby-resp-image-image\" src=\"/static/a1b1f474e4b1a1a26a65bb70a41dbf01/d9199/github-issue-2.png\" alt=\"&#x4F9D;&#x8CF4;&#x53CD;&#x8F49;&#x7BC4;&#x4F8B;&#x4E09;\" title=\"&#x4F9D;&#x8CF4;&#x53CD;&#x8F49;&#x7BC4;&#x4F8B;&#x4E09;\" loading=\"lazy\" style=\"width:100%;height:100%;margin:0;vertical-align:middle;position:absolute;top:0;left:0;\">\n      </picture>\n  </a>\n    </span>\n</figure>\n<hr></hr>\n<h2 id=\"解決方案\" style=\"position:relative;\"><a href=\"#%E8%A7%A3%E6%B1%BA%E6%96%B9%E6%A1%88\" aria-label=\"解決方案 permalink\" class=\"anchor before\"><svg aria-hidden=\"true\" focusable=\"false\" height=\"16\" version=\"1.1\" viewBox=\"0 0 16 16\" width=\"16\"><path fill-rule=\"evenodd\" d=\"M4 9h1v1H4c-1.5 0-3-1.69-3-3.5S2.55 3 4 3h4c1.45 0 3 1.69 3 3.5 0 1.41-.91 2.72-2 3.25V8.59c.58-.45 1-1.27 1-2.09C10 5.22 8.98 4 8 4H4c-.98 0-2 1.22-2 2.5S3 9 4 9zm9-3h-1v1h1c1 0 2 1.22 2 2.5S13.98 12 13 12H9c-.98 0-2-1.22-2-2.5 0-.83.42-1.64 1-2.09V6.25c-1.09.53-2 1.84-2 3.25C6 11.31 7.55 13 9 13h4c1.45 0 3-1.69 3-3.5S14.5 6 13 6z\"></path></svg></a>解決方案</h2>\n<ul>\n<li>降版到 Jest 23 -> 失敗！</li>\n<li>Add <code class=\"language-text\">--expose-gc</code> -> 成功 !?</li>\n<li><code class=\"language-text\">--max-old-space-size</code> -> 成功 ! </li>\n</ul>\n<hr></hr>\n<h2 id=\"--expose-gc\" style=\"position:relative;\"><a href=\"#--expose-gc\" aria-label=\"  expose gc permalink\" class=\"anchor before\"><svg aria-hidden=\"true\" focusable=\"false\" height=\"16\" version=\"1.1\" viewBox=\"0 0 16 16\" width=\"16\"><path fill-rule=\"evenodd\" d=\"M4 9h1v1H4c-1.5 0-3-1.69-3-3.5S2.55 3 4 3h4c1.45 0 3 1.69 3 3.5 0 1.41-.91 2.72-2 3.25V8.59c.58-.45 1-1.27 1-2.09C10 5.22 8.98 4 8 4H4c-.98 0-2 1.22-2 2.5S3 9 4 9zm9-3h-1v1h1c1 0 2 1.22 2 2.5S13.98 12 13 12H9c-.98 0-2-1.22-2-2.5 0-.83.42-1.64 1-2.09V6.25c-1.09.53-2 1.84-2 3.25C6 11.31 7.55 13 9 13h4c1.45 0 3-1.69 3-3.5S14.5 6 13 6z\"></path></svg></a><code class=\"language-text\">--expose-gc</code></h2>\n<ul>\n<li>執行 Node.js 時，在 global 物件底下新增 <code class=\"language-text\">gc</code> function</li>\n<li>gc = garbage collect</li>\n<li>善意提醒 Node.js 清理 unused heap memory</li>\n<li>process.memoryUsage()</li>\n<li>Q: heapTotal &#x26; heapUsed 到底不同在哪邊？</li>\n</ul>\n<hr></hr>\n<h2 id=\"為什麼加---expose-gc-有用？\" style=\"position:relative;\"><a href=\"#%E7%82%BA%E4%BB%80%E9%BA%BC%E5%8A%A0---expose-gc-%E6%9C%89%E7%94%A8%EF%BC%9F\" aria-label=\"為什麼加   expose gc 有用？ permalink\" class=\"anchor before\"><svg aria-hidden=\"true\" focusable=\"false\" height=\"16\" version=\"1.1\" viewBox=\"0 0 16 16\" width=\"16\"><path fill-rule=\"evenodd\" d=\"M4 9h1v1H4c-1.5 0-3-1.69-3-3.5S2.55 3 4 3h4c1.45 0 3 1.69 3 3.5 0 1.41-.91 2.72-2 3.25V8.59c.58-.45 1-1.27 1-2.09C10 5.22 8.98 4 8 4H4c-.98 0-2 1.22-2 2.5S3 9 4 9zm9-3h-1v1h1c1 0 2 1.22 2 2.5S13.98 12 13 12H9c-.98 0-2-1.22-2-2.5 0-.83.42-1.64 1-2.09V6.25c-1.09.53-2 1.84-2 3.25C6 11.31 7.55 13 9 13h4c1.45 0 3-1.69 3-3.5S14.5 6 13 6z\"></path></svg></a>為什麼加 <code class=\"language-text\">--expose-gc</code> 有用？</h2>\n<figure style=\"max-width: 600px\">\n\t<span class=\"gatsby-resp-image-wrapper\" style=\"position: relative; display: block; margin-left: auto; margin-right: auto; max-width: 930px; \">\n      <a class=\"gatsby-resp-image-link\" href=\"/static/4503e009875ff32b7f5108af3730f744/416ee/jest-source-1.png\" style=\"display: block\" target=\"_blank\" rel=\"noopener\">\n    <span class=\"gatsby-resp-image-background-image\" style=\"padding-bottom: 34.166666666666664%; position: relative; bottom: 0; left: 0; background-image: url(&apos;data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAABQAAAAHCAYAAAAIy204AAAACXBIWXMAAAsSAAALEgHS3X78AAABA0lEQVQoz5VR2W6EMAzk/z+wh6qyZdkuG0g4Q+4wdQI8VKq0qqXRSPbEHsfFajwqblB1Gl+EWhjUXGfcepNrk/IIIcD55yjm1eD9KvBadXgjvtwHvJR3fNQcfHZgo8WsHIk9rHuOwjsHoxWwRWyrRMcYqmuFpmnQdgI3sTu/tBpilNlp3DbE+DcKT5O11shBYs5afJYlvpseDz5lZ4GEPsT8ANRsy3TyjjNyQ6XU0S9gkRLLvMCuDsE7/CfSkF8OE3POISaFund0IJuxSAVGXyH4iJ4ZDK0BbySGWaFs94M6+r/DYYC1NrszB/t8sQhHa6ZVQ0wcci1QPqTcwacmkiY5/AH7UiAzpcJrqwAAAABJRU5ErkJggg==&apos;); background-size: cover; display: block;\"></span>\n  <picture>\n        <source srcset=\"/static/4503e009875ff32b7f5108af3730f744/8ac56/jest-source-1.webp 240w,\n/static/4503e009875ff32b7f5108af3730f744/d3be9/jest-source-1.webp 480w,\n/static/4503e009875ff32b7f5108af3730f744/6eb96/jest-source-1.webp 930w\" sizes=\"(max-width: 930px) 100vw, 930px\" type=\"image/webp\">\n        <source srcset=\"/static/4503e009875ff32b7f5108af3730f744/8ff5a/jest-source-1.png 240w,\n/static/4503e009875ff32b7f5108af3730f744/e85cb/jest-source-1.png 480w,\n/static/4503e009875ff32b7f5108af3730f744/416ee/jest-source-1.png 930w\" sizes=\"(max-width: 930px) 100vw, 930px\" type=\"image/png\">\n        <img class=\"gatsby-resp-image-image\" src=\"/static/4503e009875ff32b7f5108af3730f744/416ee/jest-source-1.png\" alt=\"&#x4F9D;&#x8CF4;&#x53CD;&#x8F49;&#x7BC4;&#x4F8B;&#x4E09;\" title=\"&#x4F9D;&#x8CF4;&#x53CD;&#x8F49;&#x7BC4;&#x4F8B;&#x4E09;\" loading=\"lazy\" style=\"width:100%;height:100%;margin:0;vertical-align:middle;position:absolute;top:0;left:0;\">\n      </picture>\n  </a>\n    </span>\n</figure>\n<hr></hr>\n<h2 id=\"--max-old-space-sizesize\" style=\"position:relative;\"><a href=\"#--max-old-space-sizesize\" aria-label=\"  max old space sizesize permalink\" class=\"anchor before\"><svg aria-hidden=\"true\" focusable=\"false\" height=\"16\" version=\"1.1\" viewBox=\"0 0 16 16\" width=\"16\"><path fill-rule=\"evenodd\" d=\"M4 9h1v1H4c-1.5 0-3-1.69-3-3.5S2.55 3 4 3h4c1.45 0 3 1.69 3 3.5 0 1.41-.91 2.72-2 3.25V8.59c.58-.45 1-1.27 1-2.09C10 5.22 8.98 4 8 4H4c-.98 0-2 1.22-2 2.5S3 9 4 9zm9-3h-1v1h1c1 0 2 1.22 2 2.5S13.98 12 13 12H9c-.98 0-2-1.22-2-2.5 0-.83.42-1.64 1-2.09V6.25c-1.09.53-2 1.84-2 3.25C6 11.31 7.55 13 9 13h4c1.45 0 3-1.69 3-3.5S14.5 6 13 6z\"></path></svg></a><code class=\"language-text\">--max-old-space-size=SIZE</code></h2>\n<ul>\n<li>當 unused heap memory \b接近指定的用量的時候，V8 引擎會花更多時間在 garbage collection 上</li>\n</ul>\n<div class=\"gatsby-highlight\" data-language=\"js\"><pre class=\"language-js\"><code class=\"language-js\"> <span class=\"token constant\">PASS</span>  src<span class=\"token operator\">/</span><span class=\"token operator\">...</span><span class=\"token operator\">/</span>JourneyChart<span class=\"token punctuation\">.</span>test<span class=\"token punctuation\">.</span><span class=\"token function\">js</span> <span class=\"token punctuation\">(</span><span class=\"token number\">6.902</span>s<span class=\"token punctuation\">,</span> <span class=\"token number\">135</span> <span class=\"token constant\">MB</span> heap size<span class=\"token punctuation\">)</span>\n <span class=\"token constant\">PASS</span>  src<span class=\"token operator\">/</span><span class=\"token operator\">...</span><span class=\"token operator\">/</span>CreativePanel<span class=\"token punctuation\">.</span>test<span class=\"token punctuation\">.</span><span class=\"token function\">js</span> <span class=\"token punctuation\">(</span><span class=\"token number\">131</span> <span class=\"token constant\">MB</span> heap size<span class=\"token punctuation\">)</span>\n <span class=\"token operator\">...</span>\n <span class=\"token constant\">PASS</span>  src<span class=\"token operator\">/</span><span class=\"token operator\">...</span><span class=\"token operator\">/</span>ScenarioToolbar<span class=\"token punctuation\">.</span>test<span class=\"token punctuation\">.</span><span class=\"token function\">js</span> <span class=\"token punctuation\">(</span><span class=\"token number\">893</span> <span class=\"token constant\">MB</span> heap size<span class=\"token punctuation\">)</span>\n <span class=\"token constant\">PASS</span>  src<span class=\"token operator\">/</span><span class=\"token operator\">...</span><span class=\"token operator\">/</span>CreativeImagesAction<span class=\"token punctuation\">.</span>test<span class=\"token punctuation\">.</span><span class=\"token function\">js</span> <span class=\"token punctuation\">(</span><span class=\"token number\">916</span> <span class=\"token constant\">MB</span> heap size<span class=\"token punctuation\">)</span>\n \n <span class=\"token punctuation\">(</span>everytime it reachs <span class=\"token number\">1024</span>MB<span class=\"token punctuation\">,</span> it will swipe ununsed memory<span class=\"token punctuation\">)</span>\n \n <span class=\"token constant\">PASS</span>  src<span class=\"token operator\">/</span><span class=\"token operator\">...</span><span class=\"token operator\">/</span>validateAudiencePlatform<span class=\"token punctuation\">.</span>test<span class=\"token punctuation\">.</span><span class=\"token function\">js</span> <span class=\"token punctuation\">(</span><span class=\"token number\">180</span> <span class=\"token constant\">MB</span> heap size<span class=\"token punctuation\">)</span>\n <span class=\"token constant\">PASS</span>  src<span class=\"token operator\">/</span><span class=\"token operator\">...</span><span class=\"token operator\">/</span>validateHtmlCreative<span class=\"token punctuation\">.</span>test<span class=\"token punctuation\">.</span><span class=\"token function\">js</span> <span class=\"token punctuation\">(</span><span class=\"token number\">186</span> <span class=\"token constant\">MB</span> heap size<span class=\"token punctuation\">)</span>\n <span class=\"token operator\">...</span>\n <span class=\"token punctuation\">(</span>end<span class=\"token punctuation\">)</span></code></pre></div>\n<hr></hr>\n<p><img src=\"https://cdn0-manfashion.techbang.com/system/excerpt_images/11969/mobile_inpage/c0194e50f4db09e33d417305df523752.jpg?1598596622\"></p>\n<hr></hr>\n<h2 id=\"兩種層級的-memory-leak\" style=\"position:relative;\"><a href=\"#%E5%85%A9%E7%A8%AE%E5%B1%A4%E7%B4%9A%E7%9A%84-memory-leak\" aria-label=\"兩種層級的 memory leak permalink\" class=\"anchor before\"><svg aria-hidden=\"true\" focusable=\"false\" height=\"16\" version=\"1.1\" viewBox=\"0 0 16 16\" width=\"16\"><path fill-rule=\"evenodd\" d=\"M4 9h1v1H4c-1.5 0-3-1.69-3-3.5S2.55 3 4 3h4c1.45 0 3 1.69 3 3.5 0 1.41-.91 2.72-2 3.25V8.59c.58-.45 1-1.27 1-2.09C10 5.22 8.98 4 8 4H4c-.98 0-2 1.22-2 2.5S3 9 4 9zm9-3h-1v1h1c1 0 2 1.22 2 2.5S13.98 12 13 12H9c-.98 0-2-1.22-2-2.5 0-.83.42-1.64 1-2.09V6.25c-1.09.53-2 1.84-2 3.25C6 11.31 7.55 13 9 13h4c1.45 0 3-1.69 3-3.5S14.5 6 13 6z\"></path></svg></a>兩種層級的 Memory Leak</h2>\n<ul>\n<li>Node.js 心裡有偵測到 unused memory 很多，但 Node.js <del>不說</del> 不釋放</li>\n<li>Node.js 真的沒偵測到那塊 unused memory</li>\n</ul>\n<figure style=\"max-width: 600px\">\n\t<span class=\"gatsby-resp-image-wrapper\" style=\"position: relative; display: block; margin-left: auto; margin-right: auto; max-width: 800px; \">\n      <a class=\"gatsby-resp-image-link\" href=\"/static/1d70bda16bd858959ab41d0ae8a09930/5a190/true-memory-leak.png\" style=\"display: block\" target=\"_blank\" rel=\"noopener\">\n    <span class=\"gatsby-resp-image-background-image\" style=\"padding-bottom: 25%; position: relative; bottom: 0; left: 0; background-image: url(&apos;data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAABQAAAAFCAYAAABFA8wzAAAACXBIWXMAAAsSAAALEgHS3X78AAAAa0lEQVQY07XOzQpAQBSGYX8lQoOGLGTHBSi3YD1bZeP+L8KrvsSeU0/nNNOZ+Tzvx0rRaw7EIEeCCiGsupFId3f56hMOzQ0K7JgxYkMHhwwLVn3m9PCrSi0Ej5StXCkHLV2pYnWrs1qpv68Tkx8EpnHbKfIAAAAASUVORK5CYII=&apos;); background-size: cover; display: block;\"></span>\n  <picture>\n        <source srcset=\"/static/1d70bda16bd858959ab41d0ae8a09930/8ac56/true-memory-leak.webp 240w,\n/static/1d70bda16bd858959ab41d0ae8a09930/d3be9/true-memory-leak.webp 480w,\n/static/1d70bda16bd858959ab41d0ae8a09930/d00b9/true-memory-leak.webp 800w\" sizes=\"(max-width: 800px) 100vw, 800px\" type=\"image/webp\">\n        <source srcset=\"/static/1d70bda16bd858959ab41d0ae8a09930/8ff5a/true-memory-leak.png 240w,\n/static/1d70bda16bd858959ab41d0ae8a09930/e85cb/true-memory-leak.png 480w,\n/static/1d70bda16bd858959ab41d0ae8a09930/5a190/true-memory-leak.png 800w\" sizes=\"(max-width: 800px) 100vw, 800px\" type=\"image/png\">\n        <img class=\"gatsby-resp-image-image\" src=\"/static/1d70bda16bd858959ab41d0ae8a09930/5a190/true-memory-leak.png\" alt=\"&#x4F9D;&#x8CF4;&#x53CD;&#x8F49;&#x7BC4;&#x4F8B;&#x4E09;\" title=\"&#x4F9D;&#x8CF4;&#x53CD;&#x8F49;&#x7BC4;&#x4F8B;&#x4E09;\" loading=\"lazy\" style=\"width:100%;height:100%;margin:0;vertical-align:middle;position:absolute;top:0;left:0;\">\n      </picture>\n  </a>\n    </span>\n</figure>\n<hr></hr>\n<h2 id=\"小結\" style=\"position:relative;\"><a href=\"#%E5%B0%8F%E7%B5%90\" aria-label=\"小結 permalink\" class=\"anchor before\"><svg aria-hidden=\"true\" focusable=\"false\" height=\"16\" version=\"1.1\" viewBox=\"0 0 16 16\" width=\"16\"><path fill-rule=\"evenodd\" d=\"M4 9h1v1H4c-1.5 0-3-1.69-3-3.5S2.55 3 4 3h4c1.45 0 3 1.69 3 3.5 0 1.41-.91 2.72-2 3.25V8.59c.58-.45 1-1.27 1-2.09C10 5.22 8.98 4 8 4H4c-.98 0-2 1.22-2 2.5S3 9 4 9zm9-3h-1v1h1c1 0 2 1.22 2 2.5S13.98 12 13 12H9c-.98 0-2-1.22-2-2.5 0-.83.42-1.64 1-2.09V6.25c-1.09.53-2 1.84-2 3.25C6 11.31 7.55 13 9 13h4c1.45 0 3-1.69 3-3.5S14.5 6 13 6z\"></path></svg></a>小結</h2>\n<ul>\n<li>\n<p>Jest options:</p>\n<ul>\n<li><code class=\"language-text\">--runInBand</code>: 讓 Jest 只用一個 worker 跑測試，且一個跑完才跑下一個</li>\n<li><code class=\"language-text\">--logHeapUsage</code>: 輸出跑到每一個測試時的 heap 使用量</li>\n</ul>\n</li>\n<li>\n<p>Node.js options:</p>\n<ul>\n<li><code class=\"language-text\">--expose-gc</code>: 讓 Node.js 的 global 變數有 gc 函數，用於要求做 garbage collection</li>\n<li><code class=\"language-text\">--max-old-space-size=SIZE</code>: 設定 unused 記憶體的上限，接近上限值時會較頻繁做 garbage collection</li>\n</ul>\n</li>\n</ul>\n<hr></hr>\n<h2 id=\"更進一步\" style=\"position:relative;\"><a href=\"#%E6%9B%B4%E9%80%B2%E4%B8%80%E6%AD%A5\" aria-label=\"更進一步 permalink\" class=\"anchor before\"><svg aria-hidden=\"true\" focusable=\"false\" height=\"16\" version=\"1.1\" viewBox=\"0 0 16 16\" width=\"16\"><path fill-rule=\"evenodd\" d=\"M4 9h1v1H4c-1.5 0-3-1.69-3-3.5S2.55 3 4 3h4c1.45 0 3 1.69 3 3.5 0 1.41-.91 2.72-2 3.25V8.59c.58-.45 1-1.27 1-2.09C10 5.22 8.98 4 8 4H4c-.98 0-2 1.22-2 2.5S3 9 4 9zm9-3h-1v1h1c1 0 2 1.22 2 2.5S13.98 12 13 12H9c-.98 0-2-1.22-2-2.5 0-.83.42-1.64 1-2.09V6.25c-1.09.53-2 1.84-2 3.25C6 11.31 7.55 13 9 13h4c1.45 0 3-1.69 3-3.5S14.5 6 13 6z\"></path></svg></a>更進一步</h2>\n<ul>\n<li>我們要如何偵測真的 Memory Leak ？</li>\n<li>上面提的都是 Node.js 的環境，Browser 環境會不同嗎？</li>\n</ul>\n<hr></hr>\n<h2 id=\"browser-環境\" style=\"position:relative;\"><a href=\"#browser-%E7%92%B0%E5%A2%83\" aria-label=\"browser 環境 permalink\" class=\"anchor before\"><svg aria-hidden=\"true\" focusable=\"false\" height=\"16\" version=\"1.1\" viewBox=\"0 0 16 16\" width=\"16\"><path fill-rule=\"evenodd\" d=\"M4 9h1v1H4c-1.5 0-3-1.69-3-3.5S2.55 3 4 3h4c1.45 0 3 1.69 3 3.5 0 1.41-.91 2.72-2 3.25V8.59c.58-.45 1-1.27 1-2.09C10 5.22 8.98 4 8 4H4c-.98 0-2 1.22-2 2.5S3 9 4 9zm9-3h-1v1h1c1 0 2 1.22 2 2.5S13.98 12 13 12H9c-.98 0-2-1.22-2-2.5 0-.83.42-1.64 1-2.09V6.25c-1.09.53-2 1.84-2 3.25C6 11.31 7.55 13 9 13h4c1.45 0 3-1.69 3-3.5S14.5 6 13 6z\"></path></svg></a>Browser 環境</h2>\n<ul>\n<li>沒有 global.gc() 可用，基本上沒有任何方法可以要求瀏覽器做 garbage collection</li>\n<li>查看 heap 使用量: console.memory / window.performance.memory</li>\n<li>devtools</li>\n</ul>\n<hr></hr>\n<h2 id=\"我們要如何偵測真的-memory-leak？\" style=\"position:relative;\"><a href=\"#%E6%88%91%E5%80%91%E8%A6%81%E5%A6%82%E4%BD%95%E5%81%B5%E6%B8%AC%E7%9C%9F%E7%9A%84-memory-leak%EF%BC%9F\" aria-label=\"我們要如何偵測真的 memory leak？ permalink\" class=\"anchor before\"><svg aria-hidden=\"true\" focusable=\"false\" height=\"16\" version=\"1.1\" viewBox=\"0 0 16 16\" width=\"16\"><path fill-rule=\"evenodd\" d=\"M4 9h1v1H4c-1.5 0-3-1.69-3-3.5S2.55 3 4 3h4c1.45 0 3 1.69 3 3.5 0 1.41-.91 2.72-2 3.25V8.59c.58-.45 1-1.27 1-2.09C10 5.22 8.98 4 8 4H4c-.98 0-2 1.22-2 2.5S3 9 4 9zm9-3h-1v1h1c1 0 2 1.22 2 2.5S13.98 12 13 12H9c-.98 0-2-1.22-2-2.5 0-.83.42-1.64 1-2.09V6.25c-1.09.53-2 1.84-2 3.25C6 11.31 7.55 13 9 13h4c1.45 0 3-1.69 3-3.5S14.5 6 13 6z\"></path></svg></a>我們要如何偵測真的 Memory Leak？</h2>\n<ul>\n<li>所謂 ”真的 Memory Leak“，代表的就是我們的 code 沒寫好，有一塊記憶體沒有釋放掉</li>\n<li>任何自動化的程式基本上無從得知那一塊沒被釋放掉的記憶體，到底是真的有要用，還是沒有</li>\n<li>不過，我們可以用工具提醒我們「可能」有 Memory Leak</li>\n<li>我們也可以盡可能知道什麼寫法會造成 Memory Leak</li>\n</ul>\n<hr></hr>\n<h2 id=\"偵測可能的-memory-leak-方法\" style=\"position:relative;\"><a href=\"#%E5%81%B5%E6%B8%AC%E5%8F%AF%E8%83%BD%E7%9A%84-memory-leak-%E6%96%B9%E6%B3%95\" aria-label=\"偵測可能的 memory leak 方法 permalink\" class=\"anchor before\"><svg aria-hidden=\"true\" focusable=\"false\" height=\"16\" version=\"1.1\" viewBox=\"0 0 16 16\" width=\"16\"><path fill-rule=\"evenodd\" d=\"M4 9h1v1H4c-1.5 0-3-1.69-3-3.5S2.55 3 4 3h4c1.45 0 3 1.69 3 3.5 0 1.41-.91 2.72-2 3.25V8.59c.58-.45 1-1.27 1-2.09C10 5.22 8.98 4 8 4H4c-.98 0-2 1.22-2 2.5S3 9 4 9zm9-3h-1v1h1c1 0 2 1.22 2 2.5S13.98 12 13 12H9c-.98 0-2-1.22-2-2.5 0-.83.42-1.64 1-2.09V6.25c-1.09.53-2 1.84-2 3.25C6 11.31 7.55 13 9 13h4c1.45 0 3-1.69 3-3.5S14.5 6 13 6z\"></path></svg></a>偵測可能的 Memory Leak 方法</h2>\n<ul>\n<li><a href=\"https://github.com/lloyd/node-memwatch\" target=\"_blank\" rel=\"nofollow noopener noreferrer\">node-memwatch</a>: 連續 5 次 garbage collection，heap usage 仍然上升</li>\n<li><a href=\"http://plasma-umass.org/BLeak/\" target=\"_blank\" rel=\"nofollow noopener noreferrer\">BLeak</a>: \b在 browser 端自動化偵測 Memory Leak 的工具，有 24 頁的論文可以看</li>\n<li>\n<p><a href=\"https://docs.google.com/presentation/d/1wUVmf78gG-ra5aOxvTfYdiLkdGaR9OhXRnOlIcEmu2s/pub?start=false&#x26;loop=false&#x26;delayms=3000&#x26;slide=id.g1d65bdf6_0_0\" target=\"_blank\" rel=\"nofollow noopener noreferrer\">3-snapshot technique</a>: Google 當初解 Gmail website memory leak 的方法</p>\n<ul>\n<li>Snapshot 1 -> do stuff -> snapsht 2 -> do same stuff -> snapshot 3 -> Compare snapshot 1, 2, 3</li>\n</ul>\n</li>\n<li><a href=\"https://media-codings.com/articles/automatically-detect-memory-leaks-with-puppeteer\" target=\"_blank\" rel=\"nofollow noopener noreferrer\">Detect memory leak by puppteer</a></li>\n</ul>\n<hr></hr>\n<h2 id=\"哪些-pattern-會造成-memory-leak-\" style=\"position:relative;\"><a href=\"#%E5%93%AA%E4%BA%9B-pattern-%E6%9C%83%E9%80%A0%E6%88%90-memory-leak-\" aria-label=\"哪些 pattern 會造成 memory leak  permalink\" class=\"anchor before\"><svg aria-hidden=\"true\" focusable=\"false\" height=\"16\" version=\"1.1\" viewBox=\"0 0 16 16\" width=\"16\"><path fill-rule=\"evenodd\" d=\"M4 9h1v1H4c-1.5 0-3-1.69-3-3.5S2.55 3 4 3h4c1.45 0 3 1.69 3 3.5 0 1.41-.91 2.72-2 3.25V8.59c.58-.45 1-1.27 1-2.09C10 5.22 8.98 4 8 4H4c-.98 0-2 1.22-2 2.5S3 9 4 9zm9-3h-1v1h1c1 0 2 1.22 2 2.5S13.98 12 13 12H9c-.98 0-2-1.22-2-2.5 0-.83.42-1.64 1-2.09V6.25c-1.09.53-2 1.84-2 3.25C6 11.31 7.55 13 9 13h4c1.45 0 3-1.69 3-3.5S14.5 6 13 6z\"></path></svg></a>哪些 Pattern 會造成 memory leak ?</h2>\n<ul>\n<li>不小心用到全域變數</li>\n<li>忘記移除 timer </li>\n<li>忘記移除 event listener</li>\n<li>closure</li>\n</ul>\n<hr></hr>\n<h2 id=\"總結\" style=\"position:relative;\"><a href=\"#%E7%B8%BD%E7%B5%90\" aria-label=\"總結 permalink\" class=\"anchor before\"><svg aria-hidden=\"true\" focusable=\"false\" height=\"16\" version=\"1.1\" viewBox=\"0 0 16 16\" width=\"16\"><path fill-rule=\"evenodd\" d=\"M4 9h1v1H4c-1.5 0-3-1.69-3-3.5S2.55 3 4 3h4c1.45 0 3 1.69 3 3.5 0 1.41-.91 2.72-2 3.25V8.59c.58-.45 1-1.27 1-2.09C10 5.22 8.98 4 8 4H4c-.98 0-2 1.22-2 2.5S3 9 4 9zm9-3h-1v1h1c1 0 2 1.22 2 2.5S13.98 12 13 12H9c-.98 0-2-1.22-2-2.5 0-.83.42-1.64 1-2.09V6.25c-1.09.53-2 1.84-2 3.25C6 11.31 7.55 13 9 13h4c1.45 0 3-1.69 3-3.5S14.5 6 13 6z\"></path></svg></a>總結</h2>\n<ul>\n<li>兩種層級的 memory leak</li>\n<li>沒有自動化的工具告訴我們是否真的有 memory leak ，以及 leak 在哪邊</li>\n<li>但 Chrome devtools 很實用</li>\n<li>我們也可以記得哪些 pattern 會有 memory leak</li>\n</ul>\n<hr></hr>\n<h2 id=\"待探索\" style=\"position:relative;\"><a href=\"#%E5%BE%85%E6%8E%A2%E7%B4%A2\" aria-label=\"待探索 permalink\" class=\"anchor before\"><svg aria-hidden=\"true\" focusable=\"false\" height=\"16\" version=\"1.1\" viewBox=\"0 0 16 16\" width=\"16\"><path fill-rule=\"evenodd\" d=\"M4 9h1v1H4c-1.5 0-3-1.69-3-3.5S2.55 3 4 3h4c1.45 0 3 1.69 3 3.5 0 1.41-.91 2.72-2 3.25V8.59c.58-.45 1-1.27 1-2.09C10 5.22 8.98 4 8 4H4c-.98 0-2 1.22-2 2.5S3 9 4 9zm9-3h-1v1h1c1 0 2 1.22 2 2.5S13.98 12 13 12H9c-.98 0-2-1.22-2-2.5 0-.83.42-1.64 1-2.09V6.25c-1.09.53-2 1.84-2 3.25C6 11.31 7.55 13 9 13h4c1.45 0 3-1.69 3-3.5S14.5 6 13 6z\"></path></svg></a>待探索</h2>\n<ul>\n<li>Chrome devtools 的 heap snapshot 功能</li>\n<li>自動化在 browser 端檢測 memory leak 的方法，並加入 e2e testing</li>\n<li>react 上面會有 memory leak 的 pattern</li>\n</ul>","fields":{"slug":"/posts/js-memory-leak","tagSlugs":["/tag/jest/","/tag/testing/","/tag/node-js/","/tag/out-of-memory/","/tag/garbgage-collection/","/tag/memory-leak/"]},"frontmatter":{"date":"2021-01-24T19:12:04.772Z","description":"Jest 是一款測試執行套件，是 Javascript 領域裡面最有名的測試執行套件，由 Facebook 維護。寫過 Javascript 的人多少使用過它，但卻有可能遇到記憶體不足的問題。本篇便是解釋如何解決記憶體不足的問題。","tags":["Jest","Testing","Node.js","Out Of Memory","Garbgage collection","Memory Leak"],"title":"JS Memory Leak 簡單也不簡單","socialImage":{"publicURL":"/static/eeba515438f6b88c4b710090f9405159/di-media.jpg"}}}},"pageContext":{"slug":"/posts/js-memory-leak"}},"staticQueryHashes":["251939775","401334301","825871152"]}