Can somebody explain the --predictable flag?

77 views
Skip to first unread message

Brandon Jonson

unread,
Sep 24, 2017, 11:52:43 PM9/24/17
to v8-users
Hello All! 

I have V8 embedded in a multi threaded app. The app uses locker/unlocker and all seems to work just fine in those regards (no locker errors or full on app crashes). I do have an edge case though I thought I'd get some input on. If I basically pound the isolate (utilizing locker of course) from multiple threads v8 will eventually FREEZE on a resolve and never respond. Below is the line it freezes on...

resolver->Resolve(String::NewFromUtf8(isolate, msg));

It doesn't crash the app...it just won't ever move on from that line of code, waiting for V8. It's as if V8 decided to just not respond anymore but I'm not seeing any indication of an error. Also if I change this to an actual function call it will do the same thing (so not necessarily Promise related).

The crazy thing is that when I add the --predictable flag that issue goes away. I understand they replaced set_max_available_threads, allowing the Platform to handle the work and that this --predictable flag basically forces the Platform to use one thread for background processes (I think). My assumption the freeze is occurring because of too many threads?  

Anyway I was hoping somebody a hell of a lot smarter than me could explain what this flag is changing and what fresh hell did I open myself up to by enabling it. 

Thank You! 

Jakob Kummerow

unread,
Sep 25, 2017, 12:05:50 AM9/25/17
to v8-users
Essentially, --predictable turns off anything in V8 that is known to cause changes in behavior from one run to the next: multiple thread usage (it restricts V8 to using just one thread, no background threads at all), the random number generator in Math.random(), and anything else we could think of (which I can't think of right now ;-) ). It is intended for debugging flaky problems (by making them reproducible), but sometimes it has the side effect of hiding flaky problems...

--
--
v8-users mailing list
v8-u...@googlegroups.com
http://groups.google.com/group/v8-users
---
You received this message because you are subscribed to the Google Groups "v8-users" group.
To unsubscribe from this group and stop receiving emails from it, send an email to v8-users+unsubscribe@googlegroups.com.
For more options, visit https://groups.google.com/d/optout.

Brandon Jonson

unread,
Sep 26, 2017, 12:14:04 PM9/26/17
to v8-users
Thanks Jakob! I definitely have a flaky problem and it hides it well! If I turn off the flag and override just the MonotonicallyIncreasingTime() function to return MonotonicallyIncreasingTime() * 1000 the problem vanishes. Looks like it has to do with CallDelayedOnForegroundThread being called and causing V8 to freeze up. When I override that function the CallDelayedOnForegroundThread never gets called thus the program runs. I got a lot of research/learning to do in order to understand and resolve this one. 

Thanks,
-B-  
To unsubscribe from this group and stop receiving emails from it, send an email to v8-users+u...@googlegroups.com.

Fabio Kaminski

unread,
Sep 26, 2017, 4:41:19 PM9/26/17
to v8-users
> It doesn't crash the app...it just won't ever move on from that line of code, waiting for V8. It's as if V8 decided to just not respond anymore but I'm not seeing any indication of an error. Also if I change this to an actual function call it will do the same thing (so not necessarily Promise related).

If i were you, i would suspect that some V8 background thread is waiting for a lock you/your v8 client has acquired .. 

I guess with the answer Jacob gave you, its clear that in predictable mode the v8 works with a single thread so that a lock on isolate acquired by your app becomes a non-issue.

I do use v8 in a multi-thread env, but im doing in a way where theres only a background thread per-isolate, so the consumer threads (the frontend), have to dispatch to the backend threads to have some work done.

I dont know if the context can be shared to more than one isolate(in my case i dont need), but if it does, you can have the best of both worlds.. just create a fixed ammount of isolate threads, and let only them manage the isolate, when theres a new request dispatch to the idle thread/isolate when the frontend asks for it.

Maybe giving your needs, you cant design that way, but if you can, it would avoid locks on the isolate.

Brandon Jonson

unread,
Sep 27, 2017, 3:02:48 PM9/27/17
to v8-users
Hey Fabio,

Yes you are absolutely correct. Somehow it was a locker issue even though I have locker and unlocker everywhere I thought I needed them. I couldn't find the exact point at which everything would get deadlocked but it didn't matter. My app was actually in a really good position to lock the entries to one thread per isolate anyways so I did that, made one global locker at the time the pump started (I had to use locker because in the app does initialization and code loading on a different thread that uses locker) and it all works smoothly again with no platform hacks. 

Thanks for responding with this info! It really helped talk me off the ledge. 

Thanks!
-B- 

Fabio Kaminski

unread,
Sep 28, 2017, 3:06:01 PM9/28/17
to v8-users
>  (I had to use locker because in the app does initialization and code loading on a different thread that uses locker) 

I dont know how you designed, but when i face a case where i need to sync with a 'v8 thread', first i always dispatch work to that thread
and use some thread synchro, where the frontend thread waits for a signaling from the thread dealing with v8.

I have this special treatment when dealing with shutdown.. i block the thread dealing with the main shutdown, until the thread dealing with v8 
does the cleanup and signals when its done.. 

I also do this also when i need to dispatch some computation on v8, where the frontend thread needs to hand back a answer. I just need to make sure the thread waiting for the v8 thread will not block the whole 
application (its not main) or some other part that need to work independent and in a async matter.

For pratical matters, when the frontend waits for the backend, its basically getting back to a fancy sync mode using  two threads, but at least this way
you provide a lock-free env to the v8 isolate. (also you can scale by adding more isolates/v8 threads that can be used for dispatching when theres a need) 

I dont know if this would work fine for your needs, but just in case it can be of some help to you..

Glad my hunch was right and that it works for you.
Reply all
Reply to author
Forward
0 new messages