-
Notifications
You must be signed in to change notification settings - Fork 200
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Memory leak with closures #480
Comments
Hmm, interesting. I wonder whether PHP cleans those up if php-v8js isn't involved at all 🤔 Have you tried returning closures from functions without v8js and been able to reproduce leaks there? Also I don't no much (hmm, anything) about PHP internals of closures, i.e. if this might be expected. Maybe worth noting: But agreed, if you create thousands of closures within the same http call you'll have a problem :) |
@stesie when you say without v8js, do you mean just vanilla PHP? <?php
function getclosure() {
return function() {
};
}
$a = getclosure(); the above doesn't report anything leaky. V8Js, per iteration, is leaking about 360bytes in my example. if i return an array of two closures, the result is the memory leak is exactly double. |
presumably that's just because the main object has a refcount because of the closure? |
and a bit more digging.... i changed my return Closure::fromCallable(function() { }); but that had the same result. Poking around in the docs, however, it states "Create and return a new anonymous function from given callback using the current scope". So (I think, though i don't know much about this area) the closure is keeping a reference to the If I 'unbind' the closure: $closure = Closure::fromCallable(function() { });
$closure = $closure->bindTo(null);
return $closure; then return static function() {
}; also works; so the problem really is just the freeing up of closures that are bound |
@stesie if v8js_free_storage is only called when the main V8Js instance is GC’d but there are closures bound to it out in the ether, then the code within that cleans up closures will never be called. Or something like that. Am I along the right lines? Any hints as to the best resolution? |
Extra: it’s not just closures. A regular object that holds a reference to V8Js will also leak. |
Do you mean running this JS leaks memory even if the result object in PHP is discarded? return {"foo":"bar"}; |
No, it was when you return something from PHP-land into JS. So by regular objects, I meant an instantiated PHP one, so doing it this way (when applied in the same way as my first example): class my8 extends \V8Js
{
public function getthing()
{
return new SomeClass();
}
} I initially thought it was a closure/anon function issue, but it’s the same with objects like this too. |
Ahh, thanks for clarifying. I have no idea how the internals work but I wonder if it could be fixed by returning a weakref and then getting the weakref value inside of the JS context?
|
Given we have control over all of the PHP stuff, it’s worth a go as a workaround. Will try it out when I get a chance and feed back! Ultimately though, it’s probably still something that would be ideally fixed within the library itself, but it’s good to have options and fallbacks :) |
One more whilst you're on a roll :)
I revisited one of the scripts that's now working. Ran it through valgrind and getting 32,000bytes lost with 100 iterations. On more complex scripts it can get pretty hefty. If i return an anonymous class, for example, from my8::getthing(), it's perfectly fine.
the output there is:
Somewhere the closure isn't being cleaned up properly, i'd imagine? Been poking around
v8js_weak_closure_callback
but not come up with anything as yet.The text was updated successfully, but these errors were encountered: