question-mark
Stuck on an issue?

Lightrun Answers was designed to reduce the constant googling that comes with debugging 3rd party libraries. It collects links to all the places you might be looking at while hunting down a tough bug.

And, if you’re still stuck at the end, we’re happy to hop on a call to see how we can help out.

Ubuntu version 9.8.3

<--- Last few GCs --->

  188996 ms: Mark-sweep 1270.6 (1438.5) -> 1270.5 (1438.5) MB, 1316.5 / 0.0 ms [allocation failure] [GC in old space requested].
  190319 ms: Mark-sweep 1270.5 (1438.5) -> 1270.5 (1438.5) MB, 1322.9 / 0.0 ms [allocation failure] [GC in old space requested].
  191677 ms: Mark-sweep 1270.5 (1438.5) -> 1276.3 (1416.5) MB, 1357.9 / 0.0 ms [last resort gc].
  193035 ms: Mark-sweep 1276.3 (1416.5) -> 1282.1 (1416.5) MB, 1357.6 / 0.0 ms [last resort gc].


<--- JS stacktrace --->

==== JS stack trace =========================================

Security context: 0x2022a52cfb51 <JS Object>
    1: createNamedNodeMap [/var/local/project/node_modules/jsdom/lib/jsdom/living/attributes.js:~124] [pc=0x2b8a8af2439b] (this=0xc5590909ae1 <an Object with map 0x25bed3869f1>,element=0x2ae6ff82af39 <an EventTargetImpl with map 0x42d480626b9>)
    2: new constructor(aka ElementImpl) [/var/local/project/node_modules/jsdom/lib/jsdom/living/nodes/Element-impl.js:99] [pc=0x2b8a8b3b741b] (this=0x2ae6ff82af...

FATAL ERROR: CALL_AND_RETRY_LAST Allocation failed - JavaScript heap out of memory
 1: node::Abort() [/usr/bin/node]
 2: 0x10b084c [/usr/bin/node]
 3: v8::Utils::ReportApiFailure(char const*, char const*) [/usr/bin/node]
 4: v8::internal::V8::FatalProcessOutOfMemory(char const*, bool) [/usr/bin/node]
 5: v8::internal::Factory::NewFillerObject(int, bool, v8::internal::AllocationSpace) [/usr/bin/node]
 6: v8::internal::Runtime_AllocateInTargetSpace(int, v8::internal::Object**, v8::internal::Isolate*) [/usr/bin/node]
 7: 0x2b8a883079a7
Aborted (core dumped)


Another memory leak:

<--- Last few GCs --->

  167580 ms: Mark-sweep 1311.0 (1435.1) -> 1299.1 (1435.1) MB, 1288.2 / 0.0 ms [allocation failure] [GC in old space requested].
  168860 ms: Mark-sweep 1299.1 (1435.1) -> 1299.1 (1435.1) MB, 1279.7 / 0.0 ms [allocation failure] [GC in old space requested].
  170198 ms: Mark-sweep 1299.1 (1435.1) -> 1303.8 (1405.1) MB, 1337.7 / 0.0 ms [last resort gc].
  171545 ms: Mark-sweep 1303.8 (1405.1) -> 1308.3 (1405.1) MB, 1347.5 / 0.0 ms [last resort gc].


<--- JS stacktrace --->

==== JS stack trace =========================================

Security context: 0x1bbb8e7cfb51 <JS Object>
    1: trim [native string.js:~364] [pc=0x3b0c6175d5c7] (this=0x1947dccf95c1 <Very long string[252184]>)
    2: _attach [/var/local/project/node_modules/jsdom/lib/jsdom/living/nodes/HTMLScriptElement-impl.js:~32] [pc=0x3b0c617e482c] (this=0x3f78f4f64599 <an EventTargetImpl with map 0x3df73fd78349>)
    3: _attach [/var/local/project/node_modules/jsdom/lib/jsdom/living/nodes/Node-impl.js:289] [pc=0x3b0c...

FATAL ERROR: CALL_AND_RETRY_LAST Allocation failed - JavaScript heap out of memory
 1: node::Abort() [/usr/bin/node]
 2: 0x10b084c [/usr/bin/node]
 3: v8::Utils::ReportApiFailure(char const*, char const*) [/usr/bin/node]
 4: v8::internal::V8::FatalProcessOutOfMemory(char const*, bool) [/usr/bin/node]
 5: v8::internal::Factory::NewRawTwoByteString(int, v8::internal::PretenureFlag) [/usr/bin/node]
 6: v8::internal::String::SlowFlatten(v8::internal::Handle<v8::internal::ConsString>, v8::internal::PretenureFlag) [/usr/bin/node]
 7: v8::internal::Runtime_StringTrim(int, v8::internal::Object**, v8::internal::Isolate*) [/usr/bin/node]
 8: 0x3b0c5e2092a7
Aborted (core dumped)

Issue Analytics

  • State:open
  • Created 7 years ago
  • Reactions:2
  • Comments:34 (9 by maintainers)

github_iconTop GitHub Comments

5reactions
noslouchcommented, Jul 15, 2021

fwiw I found the leak is more apparent when using the constructor. I was looping through an array of ~2000 filenames and loading each into memory so I could query with JSDOM.

when I was using new JSDOM('...') for each file, the heap eventually blew out, but when I used the same instance and merely replaced body.innerHTML, my script completed.

so in my case, it went from something like this…

const filenames = fs.readdirSync('./path/to/files');

const filteredFiles = filenames.filter(filename => {
  const html = fs.readFileSync(`./path/to/files/${filename}`, 'utf8')
  const { document } = new JSDOM(html).window;
  return !document.querySelector('table');
})

to this… diffs marked

+ const { document } = new JSDOM().window;
  const filenames = fs.readdirSync('./path/to/files');

  const filteredFiles = filenames.filter(filename => {
    const html = fs.readFileSync(`./path/to/files/${filename}`, 'utf8')
-   const { document } = new JSDOM(html).window;
+   document.body.innerHTML = html;
    return !document.querySelector('table');
  })

This approach also resolves the issue from this comment

compare this, which dies after a while (edited slightly to allow for reassigning to the body):

const { JSDOM } = require('JSDOM');

while (true) {
  const dom = new JSDOM('<html></html>');
}

to this, which goes on without trouble:

  const { JSDOM } = require('JSDOM');
+ const dom = new JSDOM();

  while (true) {
-   const dom = new JSDOM('<html></html>');
+   dom.window.document.body.innerHTML = '<html></html>';
  }
5reactions
abnorm1commented, May 18, 2020

I also had memory overflows and then found out that JSDOM is not intended to be used synchronously. 10-20 calls do not make a problem but 50000 do. If we look at the sources then we see: (/jsdom/lib/jsdom/browser/Window) ... ///// INITIALIZATION process.nextTick(() => { ... }); It is called within JSDOM constructor so called synchronously many times it overflows node event loop. Possibly it’s the reason of many memory leaks so async using solves the problem.

This code works bad (heap grows): for (i = 0; i < 10000; i ++) { dom = new JSDOM(s); ... }

This code works good: var i = 0; function f() { dom = new JSDOM(s); ... if (i ++ < 10000) setImmediate(f); } f();

Read more comments on GitHub >

github_iconTop Results From Across the Web

Memory leak
In computer science, a memory leak is a type of resource leak that occurs when a computer program incorrectly manages memory allocations in...
Read more >
What is Memory Leak? How can we avoid?
Memory leak occurs when programmers create a memory in heap and forget to delete it. The consequences of memory leak is that it...
Read more >
Memory Leaks and Garbage Collection
DEFINITION A memory leak is the gradual deterioration of system performance that occurs over time as the result of the fragmentation of a...
Read more >
Definition of memory leak
When memory is allocated, but not deallocated, a memory leak occurs (the memory has leaked out of the computer). If too many memory...
Read more >
Java Memory Leaks: Solutions, Tools, Tutorials & More
We put together this guide to help you understand how, why, and where Java memory leaks happen – and what you can do...
Read more >

github_iconTop Related Medium Post

No results found

github_iconTop Related StackOverflow Question

No results found

github_iconTroubleshoot Live Code

Lightrun enables developers to add logs, metrics and snapshots to live code - no restarts or redeploys required.
Start Free

github_iconTop Related Reddit Thread

No results found

github_iconTop Related Hackernoon Post

No results found

github_iconTop Related Tweet

No results found

github_iconTop Related Dev.to Post

No results found

github_iconTop Related Hashnode Post

No results found