Best steps to debug a JavaScript heap out of memor

2019-08-24 13:48发布

问题:

The Error:

So I get something that looks like this:

<--- Last few GCs --->

[53206:0x104800000]    14400 ms: Mark-sweep 854.6 (956.2) -> 854.6 (916.7) MB, 47.2 / 0.0 ms  (average mu = 0.871, current mu = 0.000) last resort GC in old space requested
[53206:0x104800000]    14445 ms: Mark-sweep 854.6 (916.7) -> 854.6 (915.2) MB, 44.3 / 0.0 ms  (average mu = 0.754, current mu = 0.000) last resort GC in old space requested

 <--- JS stacktrace --->

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

     0: ExitFrame [pc: 0x32ff55ecfc7d]
 Security context: 0x04eea581d9b1 <JSObject>
     1: byteLength(aka byteLength) [0x4ee3fcd6129] [buffer.js:522] [bytecode=0x4ee55266c61 offset=204](this=0x04ee450825b1 <undefined>,0x04ee72d252e1 <Very long string[433772571]>,0x04eea587f519 <String[4]: utf8>)
     2: arguments adaptor frame: 3->2
     3: fromString(aka fromString) [0x4ee3fcef989] [buffer.js:333] [bytecode=0x4ee552620b9 offset=77](this=0x04...

 FATAL ERROR: CALL_AND_RETRY_LAST Allocation failed - JavaScript heap out of memory
  1: 0x1000645d3 node::Abort() [/usr/local/Cellar/node/11.12.0/bin/node]
  2: 0x100064c5b node::OnFatalError(char const*, char const*) [/usr/local/Cellar/node/11.12.0/bin/node]
  3: 0x10017e40f v8::Utils::ReportOOMFailure(v8::internal::Isolate*, char const*, bool) [/usr/local/Cellar/node/11.12.0/bin/node]
  4: 0x10017e3b0 v8::internal::V8::FatalProcessOutOfMemory(v8::internal::Isolate*, char const*, bool) [/usr/local/Cellar/node/11.12.0/bin/node]
  5: 0x100440714 v8::internal::Heap::UpdateSurvivalStatistics(int) [/usr/local/Cellar/node/11.12.0/bin/node]
  6: 0x10044681e v8::internal::Heap::SetUp() [/usr/local/Cellar/node/11.12.0/bin/node]
  7: 0x1004269af v8::internal::Factory::AllocateRawWithImmortalMap(int, v8::internal::PretenureFlag, v8::internal::Map*, v8::internal::AllocationAlignment) [/usr/local/Cellar/node/11.12.0/bin/node]
  8: 0x100428511 v8::internal::Factory::NewRawTwoByteString(int, v8::internal::PretenureFlag) [/usr/local/Cellar/node/11.12.0/bin/node]
  9: 0x100505f5e v8::internal::String::SlowFlatten(v8::internal::Isolate*, v8::internal::Handle<v8::internal::ConsString>, v8::internal::PretenureFlag) [/usr/local/Cellar/node/11.12.0/bin/node]
 10: 0x1001921f1 v8::String::Utf8Length(v8::Isolate*) const [/usr/local/Cellar/node/11.12.0/bin/node]
 11: 0x10004cd13 node::Buffer::(anonymous namespace)::ByteLengthUtf8(v8::FunctionCallbackInfo<v8::Value> const&) [/usr/local/Cellar/node/11.12.0/bin/node]
 12: 0x1001e2ac4 v8::internal::FunctionCallbackArguments::Call(v8::internal::CallHandlerInfo*) [/usr/local/Cellar/node/11.12.0/bin/node]
 13: 0x1001e2124 v8::internal::MaybeHandle<v8::internal::Object> v8::internal::(anonymous namespace)::HandleApiCallHelper<false>(v8::internal::Isolate*, v8::internal::Handle<v8::internal::HeapObject>, v8::internal::Handle<v8::internal::HeapObject>, v8::internal::Handle<v8::internal::FunctionTemplateInfo>, v8::internal::Handle<v8::internal::Object>, v8::internal::BuiltinArguments) [/usr/local/Cellar/node/11.12.0/bin/node]
 14: 0x1001e1944 v8::internal::Builtin_Impl_HandleApiCall(v8::internal::BuiltinArguments, v8::internal::Isolate*) [/usr/local/Cellar/node/11.12.0/bin/node]
 15: 0x32ff55ecfc7d

and I have absolutely no idea how to even start debugging this. I've looked at similar questions "Javascript heap out of memory" and understand that I can increase the memory limit (which seams to be the most commonly suggested solution).


The Code

The function that is causing the error is an express controller looking something like this (simplified):

const foo = async (req,res) => {
   // get users in chat room
   const users = await db.getUsers(req.query.roomId);
   res.send(users);
}

The error came when I added another user to the room. I've also checked that the error disappears if I filter out the last added user. From print-debugging I've also seen that all code executes up to the res.send statement so it seems the error is happening in that function.


The Question

The reason I'm hesitant at just adding more memory is that I'm just pushing the problem further away and instead of crashing at 6 users it will crash at 15 or 30 users.

So I would like to debug the script (perhaps see how much memory the users object takes up and how different forms of optimisations would affect that.

I simply don't know how to debug these kind of low level errors and wonder if there are some standard you can go through when encountering this kind of error?


PS: Just found it kinda funny that the top suggested similar question is:

How to create an HTML button that acts like a link?