No worries,
Rubberducking is quite efficient sometimes! ;)

Feel free to send a pull request  <https://v8.dev/docs/contribute>and we
can have a look at it!

cheers,
Camillo

On Mon, 3 Aug 2020 at 13:58, Alex Kodat <alexko...@gmail.com> wrote:

> OK, now I'm replying to myself a second time. Really sorry. I realized we
> don't need any enhancement to sampling other than getting the non-check for
> Isolate locked by debugged (suspended) thread fixed in Windows. For
> sampling when Isolate is unlocked I can simply get time before and after an
> unlock on a profiled thread, do a StackTrace::CurrentStackTrace() and use
> that information to merge with the CpuProfiler::StopProfiling results,
> converting timer units to ticks. Not exactly rocket science.
>
> So the simple question then is should I do a PR to fix the sampling issue
> on Windows?
>
> Thanks and sorry about all the noise.
>
> On Sunday, August 2, 2020 at 3:04:03 PM UTC-5, Alex Kodat wrote:
>>
>> We're using the CpuProfiler in an Isolate that can have multiple threads
>> running and and taking turns in the Isolate via Unlocker. Frequently, we
>> want to profile what's happening on a thread so we do a StartProfiling for
>> a thread, let it run for a while, and then collect the results via
>> StopProfiling. Works great.
>>
>> However, I've noticed a difference between Windows and Linux in the
>> profiles, specifically, Windows collects samples for a thread when it's
>> inside an Unlocker bracket whereas Linux does not. So if we have a native
>> function sleep(), that unlocks the Isolate, in Windows I see a high hit
>> count for stacks that have functionName "sleep" and sourceType callback in
>> the bottom stack entry. In Linux, there are no hits where I'm inside the
>> sleep native function. For our purposes, the Windows behavior is much nicer
>> as we can easily see how much of the thread's time is being spent in sleep.
>> In Linux, there is absolutely no way of knowing because the information is
>> not captured.
>>
>> Unfortunately, Windows nicer (IMO) behavior comes at a cost.
>> Specifically, if indeed other threads do run in the Isolate while the
>> profiled thread is sampled when unlocked, there is a tendency for core
>> dumps while getting the stack trace. This is unsurprising because the stack
>> trace needs to look in the Isolate's heap to get things like function names
>> and that's not really a good idea when a thread doesn't have the Isolate
>> lock.
>>
>> The following code samples are all from src/libsampler/sampler.cc.
>>
>> Under Linux the profiler protects itself in SamplerManager::DoSample
>> (called by the SIGPROF handler) with:
>>
>>   for (Sampler* sampler : samplers) {
>>     ...
>>     if (v8::Locker::IsActive() && !Locker::IsLocked(isolate)) continue;
>>     sampler->SampleStack(state);
>>   }
>>
>> That Locker::isLocked is a bit of a misnomer and really means
>> Locker::isLockedByCurrentThread and, because our SIGPROF handler runs on
>> the profiled thread, if that tread is in an Unlocker bracket in a native
>> function, isLocked returns false and we don't collect a sample.
>>
>> In Windows, the sampler does not run on the profiled thread and, instead,
>> does a SuspendThread of the profiled thread from another thread and then
>> uses GetThreadContext:
>>
>> void Sampler::DoSample() {
>>   HANDLE profiled_thread = platform_data()->profiled_thread();
>>   if (profiled_thread == nullptr) return;
>>
>>   const DWORD kSuspendFailed = static_cast<DWORD>(-1);
>>   if (SuspendThread(profiled_thread) == kSuspendFailed) return;
>>
>>   // Context used for sampling the register state of the profiled thread.
>>   CONTEXT context;
>>   memset(&context, 0, sizeof(context));
>>   context.ContextFlags = CONTEXT_FULL;
>>   if (GetThreadContext(profiled_thread, &context) != 0) {
>>      ...
>>      SampleStack(state);
>>   }
>>
>> There is no check if the Isolate is actually locked by the profiled
>> thread so we can get a sample for it but also, unfortunately, seg faults
>> and the like if another thread is running.
>>
>> So it seems that there really should be a check in Sampler::DoSample for
>> Windows to check if the Isolate is locked by the profiled thread. This
>> would require maybe adding another method to Locker like
>> isLockedByThread(ThreadId id) or something like that and then checking that
>> in Sampler::DoSample. When PlatformData is instantiated for Windows it
>> could stash the ThreadId for the current thread so it could be retrieved in
>> Sampler::DoSample. Doesn't seem all that daunting and am willing to put
>> together a PR for this if this seems reasonable and unless someone more
>> conversant with V8 internals doesn't pick it up.
>>
>> However, while this fix would eliminate Windows seg faults when doing
>> profiling in a multi-threaded environment, it would also make me sad
>> because now we would have no way of getting time spent unlocked in my
>> native function. To provide this functionality, it seems like it would be
>> nice to be able to create a provisional TickSample before the Isolate is
>> unlocked in a native function and use that in DoSample if the Isolate is
>> not locked by the profiled thread. Obviously, this would/should only be
>> done if the thread is being profiled.
>>
>> There are a lot of ways this could work but a straw man is that there
>> could be CpuProfiler methods called SaveProvisionalThreadSample and
>> ClearProvisionalThreadSample. The former, at least, would have to be called
>> while one holds the Isolate lock so one would presumably do such a call
>> right before Unlocker instantiation and then do a
>> ClearProvisionalThreadSample call right after the end of the Unlocker
>> context. Then, if DoSample decides that Isolate is not locked by the
>> sampled thread, it could look for a saved provisional sample for the thread
>> and, if available, use that for its sample. Note that a provisional
>> TickSample could be used many times as a thread might be unlocked over many
>> samples.
>>
>> Again, assuming no one else picks this up, happy to take a swing at a PR,
>> myself. While more complicated than the Windows fix, it doesn't seem that
>> daunting.
>>
>> Opinions?
>>
>> Sorry if this would have been more appropriately posted on v8-dev.
>>
>> Thanks
>>
>>
> --
> --
> v8-users mailing list
> v8-users@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+unsubscr...@googlegroups.com.
> To view this discussion on the web visit
> https://groups.google.com/d/msgid/v8-users/1bd503d6-ddec-4dca-9c76-55877b84e283o%40googlegroups.com
> <https://groups.google.com/d/msgid/v8-users/1bd503d6-ddec-4dca-9c76-55877b84e283o%40googlegroups.com?utm_medium=email&utm_source=footer>
> .
>

-- 
-- 
v8-users mailing list
v8-users@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+unsubscr...@googlegroups.com.
To view this discussion on the web visit 
https://groups.google.com/d/msgid/v8-users/CAOeS1i8vLYSaNUcv-JCdhvq9yFDGp2x1S4srhp3wT_Ojyt7iWQ%40mail.gmail.com.

Reply via email to