Embedded v8 running out of memory

68 views
Skip to first unread message

andre...@gmail.com

unread,
Jul 18, 2019, 5:32:02 PM7/18/19
to v8-dev
Hi,

My application creates a lot of closures in the following manner:

v8::Local<v8::Function> myFunc = v8::Function::New(
      i
->GetCurrentContext(),
     
FunctionInvokerCallback(),
     
this->WrapDelegate(callbackInvoke),
     
0,
      v8
::ConstructorBehavior::kThrow,
      v8
::SideEffectType::kHasSideEffect).ToLocalChecked();

//persistentObject is a weak Global reference with a callback to clean up native resources
this->objectHandle->persistentObject->Get(i)->Set(i->GetCurrentContext(), functionName, myFunc).FromJust();

Reason I do this is because I don't want to always create FunctionTemplates (which would eventually blow the memory as they're never cleaned up).

What I'm finding is that eventually V8 runs out of memory (Heap is full). When I look at a heap shapshot, I see that pretty much all of the retained memory is taken up by noscript_shared_function_infos in Strong roots. I know that  this is weak array that keeps track of all of these functions. Does this mean that my Functions are created but never deleted? If so, is there a way to explicitly delete them and then the array should be compacted next GC run. Alternatively, it would be nice to create such a function in the context of my object so the function would be cleaned up when the object is

Snapshot:

sharedFunctionInfos.png



andre...@gmail.com

unread,
Jul 18, 2019, 6:21:16 PM7/18/19
to v8-dev
My guess is that it's because everything is created on one Context...but I'm not sure how to resolve this.

Ideally I'd be able to generalize my functions and create a few FunctionTemplates, but in the meantime ti would be great to clean up these functions somehow

Yang Guo

unread,
Jul 19, 2019, 3:58:08 AM7/19/19
to v8-...@googlegroups.com
Do you have any details on how you are creating the weak global reference? The way I see it is that everything survives GC.

Yang

On Fri, Jul 19, 2019 at 12:21 AM <andre...@gmail.com> wrote:
My guess is that it's because everything is created on one Context...but I'm not sure how to resolve this.

Ideally I'd be able to generalize my functions and create a few FunctionTemplates, but in the meantime ti would be great to clean up these functions somehow

--
--
v8-dev mailing list
v8-...@googlegroups.com
http://groups.google.com/group/v8-dev
---
You received this message because you are subscribed to the Google Groups "v8-dev" group.
To unsubscribe from this group and stop receiving emails from it, send an email to v8-dev+un...@googlegroups.com.
To view this discussion on the web visit https://groups.google.com/d/msgid/v8-dev/9c815ba7-821f-4337-9e46-ec6c439977ab%40googlegroups.com.
For more options, visit https://groups.google.com/d/optout.

andre...@gmail.com

unread,
Jul 19, 2019, 9:31:11 AM7/19/19
to v8-dev
I believe I'm doing it right as I see my weak callback handler get called:

v8::Global<v8::Object>* persistentObject;
...
this->objectHandle->persistentObject = new v8::Global<v8::Object>(i, obj);
this->objectHandle->persistentObject->SetWeak(this, imWeak, v8::WeakCallbackType::kParameter);

where "imWeak" cleans up the native resources.

I see the memory go up and go down after GC, ie. the following pattern:

100-150-120-160-130-170MB etc.

When the callback handler wasn't getting called at all, the memory just grew

Yang Guo

unread,
Jul 19, 2019, 9:33:31 AM7/19/19
to v8-...@googlegroups.com
I see. Are you certain that there is no other source of memory leaking?

Yang

--
--
v8-dev mailing list
v8-...@googlegroups.com
http://groups.google.com/group/v8-dev
---
You received this message because you are subscribed to the Google Groups "v8-dev" group.
To unsubscribe from this group and stop receiving emails from it, send an email to v8-dev+un...@googlegroups.com.

andre...@gmail.com

unread,
Jul 19, 2019, 9:48:44 AM7/19/19
to v8-dev
I'm not sure - I'm probably leaking native resources somewhere, but those shouldn't blow the v8 heap.

I tried looking into what noscript_shared_function_infos is (it's a weakarrayList) which should get compacted at GC time. So it looks like the functions are staying alive and either need to be manually destroyed, equivalent to:

f = function() { //do something }
....
f
= null;
or created in a way that is tied to the lifecycle of the object

alxspbmi...@gmail.com

unread,
Aug 29, 2019, 12:13:06 PM8/29/19
to v8-dev


пятница, 19 июля 2019 г., 16:48:44 UTC+3 пользователь andr...@gmail.com написал:
I have exactly same memory leak.
All what I've done is: "Creating new context from ObjectTemplate(saved in isolate internals) -> Bind & Run UnboundScript -> Execute some functions -> Destroying Context"

Screenshot from 2019-08-29 19-12-08.png

andre...@gmail.com

unread,
Aug 29, 2019, 12:35:06 PM8/29/19
to v8-dev
Nice! 

As the FunctionTemplate docs say, if you're gonna make lots of closures -- don't - use scripts instead.

My solution to this issue was to not rely on so many closures. I created another layer which creates concrete functions (via FunctionTemplate), and these functions know how to retrieve data for each object (essentially doing what closures were doing).

alxspbmi...@gmail.com

unread,
Aug 30, 2019, 10:21:33 AM8/30/19
to v8-dev


четверг, 29 августа 2019 г., 19:35:06 UTC+3 пользователь andr...@gmail.com написал:
I have random script with several functions in it. For example
function foo() { customCallback('foo'); return 'foo'; }
function bar() { return 'bar'; }
All I want is to execute it in clean=new context and then execute functions from that context. Then context could be destroyed.
This clean context needs to be created from ObjectTemplate with some preinstalled c++ function callbacks.
Full pseudocode:
while (true) {
 
auto ctx = v8::Context::New(pIsolate, nullptr, GetIsolateData(pIsolate).m_GlobalTemplate.Get(pIsolate)); // IsolateData - Embedded struct; m_GlobalTemplate = v8::Persistent<v8::ObjectTemplate>
 
auto scr = UnboundScript->BindToCurrentContext();
 
auto res = scr->Run(ctx);
 
// Executing functions from ctx->Global and manipulating with results
} // ctx is destroyed each cycle, but v8::heap increasing each cycle too up to OOM exception

On v8(6.7.x) there weren't any heap mem-leak (it was test version from some master commit and there were other issues inside)
On Chrome-stable v8(7.5.288.30) OOM
Reply all
Reply to author
Forward
0 new messages