1

An application I'm working on embeds V8 for scripting. To conserve memory, I want to shut down the scripting component when it is not needed, but for some reason the memory is never returned to the OS.

Here's what I tried:

1. Call Dispose() on the persistent context handle

context.Dispose();

2. Force a garbage collection

while (!v8::V8::IdleNotification());

None of that has any notable effect on the processes memory usage. I can clearly see how it's going up when a script claims memory, but it never goes down again.

I'm determining process memory usage with ps -o rss. I know that figuring out how much memory a process is using is not really possible without a profiler, but I do believe rss should go down when V8 lets go of the memory.

futlib
  • 8,258
  • 13
  • 40
  • 55
  • http://stackoverflow.com/questions/1421491/does-calling-free-or-delete-ever-release-memory-back-to-the-system – congusbongus Mar 08 '13 at 11:56
  • Ouch. Got to investigate that a bit. Would still be interested if anyone has solved the problem with V8 though - the only solution I can think of is to load v8 in a forked process and kill that one. – futlib Mar 08 '13 at 12:46
  • Yes that does indeed happen with a simple C program :( Still hoping for suggestions on how to make the OS reclaim the memory. – futlib Mar 08 '13 at 16:10
  • I would suggest that you need to destroy your `Isolate` (V8 instance in which the `Context` executes) too, using `V8::Isolate::Destroy()` after calling `V8::Isolate::Exit()` if the Isolate is 'Enter()'ed by your `Context` – coolhandle01 Jun 28 '18 at 09:56

2 Answers2

0

The OS may simply be not reclaiming memory (for performance reasons for example) even if your application has freed it correctly. The application heap may also be holding the memory in case you need it again quickly. Either way, if you're sure you're not leaking (try something like valgrind), I wouldn't worry about it.

mark
  • 5,269
  • 2
  • 21
  • 34
  • Experimented a bit around with this, it feels a it mysterious though. If I allocate 100 MB of memory in a little C program, the memory is never reclaimed until the program exits. If I allocate 500 MB instead, it is reclaimed almost immediately. Any idea if I can force the OS to reclaim it? – futlib Mar 08 '13 at 16:09
  • I'm guessing in your experiment you crossed some threshold where the OS and/or application heap library "decided" it was enough memory to warrant returning it to the system pool. I'm not aware of a standard way to influence those decisions... it's an implementation trade-off. For instance, what if you went ahead and allocated and freed that 100MB over and over in a loop? – mark Mar 08 '13 at 18:11
0

Just spent few hours wrestling with this and eventually had to dig into api.cc of V8.

Turns out V8 pins last instance of global object template for fast reuse (be it raw ObjectTemplate or one derived from FunctionTemplate for proxies). Which is immensely confusing when trying to force GC flush. Workaround is to allocate new dummy context (using same template as of context you're trying to flush).

static void do_gc()
{
  {
    Isolate *i = Isolate::GetCurrent();
    HandleScope h(i);
    Handle<Context> c = Context::New(i); // Default contexes
    Handle<Context> c = Context::New(i, 0, objtemplate); // With custom object
    Handle<Context> c = Context::New(i, 0, fntemplate->InstanceTemplate()); // With proxy
  }
  while (!v8::V8::IdleNotification());
}

To see usage in context https://github.com/katlogic/lv8/blob/344353dac702901c917a4c05438252121c527ab3/lv8.cpp#L755

kat
  • 814
  • 9
  • 6