Garbage collections.

99 views
Skip to first unread message

Jane Chen

unread,
Dec 7, 2016, 6:35:17 PM12/7/16
to v8-users
Just upgraded v8 from 4.6 to 5.3 and found a new behavior:  garbage collection can happen in a background thread after ContextDisposedNotification and IdleNotificationDeadline return.  My idleNotificationDeadline runs in a loop with 1sec increments, and it typically comes out after 1 or 2 iterations.

My application has its own book keeping on allocated objects, so when IdleNotificationDeadline returns, while still in the Isolate, it forcefully cleans up the leftover references held from v8 weak callback params.

Apparently starting from 5.3, a race condition starts to happen during the above routine.

I experimented using the GC callbacks to track GC activity.  But even when the callback indicates GC is done, I still run into the race condition.

I'd hate to put in a mutex just for this due to performance concerns.  Would be nice to have a reliably way to tell when GC is done.

Appreciate any advice on this.


Ben Noordhuis

unread,
Dec 8, 2016, 5:14:32 AM12/8/16
to v8-users
I don't quite understand where the race condition is. You mean you
expect weak callbacks to run before IdleNotificationDeadline()
returns? Some example code might be useful.

Jane Chen

unread,
Dec 9, 2016, 12:55:38 AM12/9/16
to v8-users
Yes, That is what I have assumed.  No?  If not, how do I find out when GC is done? 

So I now leverage LowMemoryNotification to GC before I do my own as a last resort.  With that, I get a few different stacks:

2016-12-08 16:12:25.452 Critical: Thread 116 (Thread 0x7f1fb19da700 (LWP 18574)): 2016-12-08 16:12:25.452 Critical: #0 0x000000311ca0f279 in waitpid () from /lib64/libpthread.so.0 2016-12-08 16:12:25.452 Critical: #1 0x0000000003d6d658 in xdmp::pstack() () 2016-12-08 16:12:25.452 Critical: #2 0x0000000003d6d926 in pstackSignalAction () 2016-12-08 16:12:25.452 Critical: #3 <signal handler called> 2016-12-08 16:12:25.452 Critical: #4 0x00007f1fb57991f6 in v8::internal::MarkCompactCollector::Sweeper::ParallelSweepSpace(v8::internal::AllocationSpace, int, int) () from /space/projects/head/xdmp/src/lib/libv8.so 2016-12-08 16:12:25.452 Critical: #5 0x00007f1fb57a09c9 in v8::internal::MarkCompactCollector::Sweeper::SweeperTask::Run() () from /space/projects/head/xdmp/src/lib/libv8.so

... which is apparently a background thread.

And this:
2016-12-08 16:31:45.059 Critical: Thread 40 (Thread 0x7f6b429a1700 (LWP 23345)): 2016-12-08 16:31:45.059 Critical: #0 0x000000311ca0f279 in waitpid () from /lib64/libpthread.so.0 2016-12-08 16:31:45.059 Critical: #1 0x0000000003d6d688 in xdmp::pstack() () 2016-12-08 16:31:45.059 Critical: #2 0x0000000003d6d956 in pstackSignalAction () 2016-12-08 16:31:45.059 Critical: #3 <signal handler called> 2016-12-08 16:31:45.059 Critical: #4 0x00007f7069927511 in v8::internal::MarkCompactCollector::RecordRelocSlot(v8::internal::Code*, v8::internal::RelocInfo*, v8::internal::Object*) () from /space/projects/head/xdmp/src/lib/libv8.so 2016-12-08 16:31:45.059 Critical: #5 0x00007f7069930dc3 in void v8::internal::RelocInfo::Visit<v8::internal::MarkCompactMarkingVisitor>(v8::internal::Heap*) () from /space/projects/head/xdmp/src/lib/libv8.so 2016-12-08 16:31:45.059 Critical: #6 0x00007f706992ee8b in v8::internal::StaticMarkingVisitor<v8::internal::MarkCompactMarkingVisitor>::VisitCode(v8::internal::Map*, v8::internal::HeapObject*) () from /space/projects/head/xdmp/src/lib/libv8.so 2016-12-08 16:31:45.059 Critical: #7 0x00007f706992553f in v8::internal::MarkCompactCollector::EmptyMarkingDeque() () from /space/projects/head/xdmp/src/lib/libv8.so 2016-12-08 16:31:45.059 Critical: #8 0x00007f70698f6069 in v8::internal::GlobalHandles::IterateStrongRoots(v8::internal::ObjectVisitor*) () from /space/projects/head/xdmp/src/lib/libv8.so 2016-12-08 16:31:45.059 Critical: #9 0x00007f70699107ee in v8::internal::Heap::IterateStrongRoots(v8::internal::ObjectVisitor*, v8::internal::VisitMode) () from /space/projects/head/xdmp/src/lib/libv8.so 2016-12-08 16:31:45.059 Critical: #10 0x00007f7069920905 in v8::internal::MarkCompactCollector::MarkLiveObjects() () from /space/projects/head/xdmp/src/lib/libv8.so 2016-12-08 16:31:45.059 Critical: #11 0x00007f7069920409 in v8::internal::MarkCompactCollector::CollectGarbage() () from /space/projects/head/xdmp/src/lib/libv8.so 2016-12-08 16:31:45.059 Critical: #12 0x00007f7069903ba2 in v8::internal::Heap::MarkCompact() () from /space/projects/head/xdmp/src/lib/libv8.so 2016-12-08 16:31:45.059 Critical: #13 0x00007f70699029ae in v8::internal::Heap::PerformGarbageCollection(v8::internal::GarbageCollector, v8::GCCallbackFlags) () from /space/projects/head/xdmp/src/lib/libv8.so 2016-12-08 16:31:45.059 Critical: #14 0x00007f70699020ee in v8::internal::Heap::CollectGarbage(v8::internal::GarbageCollector, char const*, char const*, v8::GCCallbackFlags) () from /space/projects/head/xdmp/src/lib/libv8.so 2016-12-08 16:31:45.059 Critical: #15 0x00007f7069901e08 in v8::internal::Heap::CollectAllAvailableGarbage(char const*) () from /space/projects/head/xdmp/src/lib/libv8.so 2016-12-08 16:31:45.059 Critical: #16 0x00007f7069606cb6 in v8::Isolate::LowMemoryNotification() () from /space/projects/head/xdmp/src/lib/libv8.so

This only happens in stress test environment, and I haven't been able to reproduce with a debug build.

Ben Noordhuis

unread,
Dec 9, 2016, 7:57:14 AM12/9/16
to v8-users
Okay, I think I see what you mean. I wouldn't expect
IdleNotificationDeadline() to run weak callbacks and I don't think it
does. A callback can take an arbitrary long time to complete so there
would be no way for IdleNotificationDeadline() to guarantee it doesn't
overrun the deadline.

You could try a double indirection scheme if freeing resources early
is important to you. Your weak callback takes a pointer to a pointer
(a slot) to your big expensive state object, your resource freeing
code frees the object and clears the slot, leaving it to your weak
callback to free the memory of the slot itself.
Reply all
Reply to author
Forward
0 new messages