Re: [v8-users] Thread cleanup

2015-10-18 Thread Alex Kodat
Sorry, I was too hasty. Obviously, one doesn't need the Isolate lock to 
remove PerIsolateThreadData from the linked list, one needs 
the thread_data_table_mutex_ lock. FWIW, it strikes me as very odd that 
ThreadDataTable is process-wide with a static pointer. Given that its lone 
data member is the chain anchor for PerIsolateThreadData objects it seems 
that a ThreadDataTable object could be inside the Isolate and not take up 
any more space and probably be protected by the Isolate lock so eliminate 
the need for a separate mutex. 

Neverthless, I was wrong and, in theory, one could have a totally 
Locker-independent call to free a thread's PerIsolateThreadData. But, since 
one could not free the current thread's PerIsolateThreadData while there is 
a Locker on the thread's stack, freeing PerIsolateThreadData still seems 
pretty tightly associated with the Locker class so I think I'd stick with 
my proposals.

Also, FWIW, I did a bit more research and the only thing of substance that 
seems to survive a top_level_ && has_lock_ Locker destruction is a thread's 
Simulator. And while, I admit I don't fully understand the Simulator code 
it seems unlikely that a thread's Simulator would hold state that would 
need to survive an unlock/lock. Admittedly, deleting and then 
reconstructing a Simulator would not be cheap but I would assume someone 
using a Simulator would not be expecting particularly high performance, 
anyway?   

On Sunday, October 18, 2015 at 11:06:27 AM UTC-7, Alex Kodat wrote:
>
> Jakob,
>
> Thanks for that. I might just take a swing at an unintrusive patch. Along 
> those lines it seems that thread resource cleanup would be closely tied to 
> the Locker as one would need the isolate lock while freeing 
> PerIsolateThreadData but would presumably want to release the lock 
> immediately after. So it seems the most logical approach would be a Locker 
> class variable called say cleanup_ that's set either with an extra 
> parameter on the Locker constructor or a Locker method to clean up at 
> destruction time (both with appropriate semantics if not top_level_ or 
> has_lock_).
>
> But just want to make sure that this couldn't be even made less intrusive 
> by just always cleaning up if top_level_ and has_lock_ in the Locker 
> destructor. As it is, in this case ThreadManager::FreeThreadResources ends 
> up being called which doesn't seem to leave a heck a lot of useful stuff 
> around for the thread so leaving a few crumbs around seems mainly an 
> efficiency issue -- if someone has a lot of top level Locker brackets in a 
> loop, there might be a bit of extra object creation/destruction if 
> ThreadManager::FreeThreadResources always does a full thread cleanup but 
> it's hard to imagine that being significant for anyone. In the unlikely 
> event that it is, an embedder can create an outer Locker with nested 
> Unlockers, an approach that would have no v8 release dependencies. 
>
> So which approach would you prefer: just do it, Locker class method, or 
> Locker constructor parameter?
>
> Thanks 
>
> On Sunday, October 18, 2015 at 4:07:07 AM UTC-7, Jakob Kummerow wrote:
>>
>> On Sun, Oct 18, 2015 at 8:16 AM, Alex Kodat  wrote:
>>
>>> If I have an app that steadily creates and joins threads, is there a 
>>> good way of cleaning up the thread-specific data when a thread terminates? 
>>> Looking at the v8 code, it seems that ThreadManager::FreeThreadResources in 
>>> v8threads.cc would be a place this might happen when called from the Locker 
>>> destructor when top_level_ is set. But maybe for good reason not all 
>>> thread-specific data seems to be cleaned up?
>>>
>>
>> Just because a thread releases a lock doesn't mean that thread is about 
>> to die. It might come back to V8 later. So any cleanup would have to be 
>> triggered explicitly by the embedder, it can't just happen automatically.
>>  
>>
>>> More specifically, as I have lots of threads use an isolate and then 
>>> terminate, their Isolate::PerIsolateThreadData remains queued off 
>>> of Isolate::ThreadDataTable list_. While this is essentially a memory leak, 
>>> even worse, the queue just gets crazy long and the master (so first Isolate 
>>> user) thread's Isolate::PerIsolateThreadData (being at the end) takes crazy 
>>> long to find. And the entire massive queue has to be scanned each time a 
>>> new thread uses the Isolate to determine that the thread does not yet have 
>>> an Isolate::PerIsolateThreadData. Eventually v8 ends up spending most of 
>>> its time scanning the Isolate::PerIsolateThreadData queue. 
>>>
>>
>> Yes.
>>  
>>
>>> The solution would be to be able to get to 
>>> Isolate::ThreadDataTable::Remove for defunct threads but I didn't see a 
>>> path there from any embedder API functions. Is there one? And it looks like 
>>> might be a few other thread-specific bits and bobs that might be left 
>>> laying around, anyway.
>>>
>>> Maybe v8 just isn't built with apps that steadily create and 

[v8-users] Thread cleanup

2015-10-18 Thread Alex Kodat
If I have an app that steadily creates and joins threads, is there a good 
way of cleaning up the thread-specific data when a thread terminates? 
Looking at the v8 code, it seems that ThreadManager::FreeThreadResources in 
v8threads.cc would be a place this might happen when called from the Locker 
destructor when top_level_ is set. But maybe for good reason not all 
thread-specific data seems to be cleaned up?

More specifically, as I have lots of threads use an isolate and then 
terminate, their Isolate::PerIsolateThreadData remains queued off 
of Isolate::ThreadDataTable list_. While this is essentially a memory leak, 
even worse, the queue just gets crazy long and the master (so first Isolate 
user) thread's Isolate::PerIsolateThreadData (being at the end) takes crazy 
long to find. And the entire massive queue has to be scanned each time a 
new thread uses the Isolate to determine that the thread does not yet have 
an Isolate::PerIsolateThreadData. Eventually v8 ends up spending most of 
its time scanning the Isolate::PerIsolateThreadData queue. 

The solution would be to be able to get to Isolate::ThreadDataTable::Remove 
for defunct threads but I didn't see a path there from any embedder API 
functions. Is there one? And it looks like might be a few other 
thread-specific bits and bobs that might be left laying around, anyway.

Maybe v8 just isn't built with apps that steadily create and destroy 
thread's in mind and such apps should just use their own thread pool 
managers and avoid allowing threads to terminate? Easy enough to do that 
though it's even easier if we don't have to -- the overhead of creating and 
joining threads is pretty tiny these days, especially relative to the "real 
work" that likely happens on each thread. 

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.
For more options, visit https://groups.google.com/d/optout.


Re: [v8-users] Thread cleanup

2015-10-18 Thread Jakob Kummerow
On Sun, Oct 18, 2015 at 8:16 AM, Alex Kodat  wrote:

> If I have an app that steadily creates and joins threads, is there a good
> way of cleaning up the thread-specific data when a thread terminates?
> Looking at the v8 code, it seems that ThreadManager::FreeThreadResources in
> v8threads.cc would be a place this might happen when called from the Locker
> destructor when top_level_ is set. But maybe for good reason not all
> thread-specific data seems to be cleaned up?
>

Just because a thread releases a lock doesn't mean that thread is about to
die. It might come back to V8 later. So any cleanup would have to be
triggered explicitly by the embedder, it can't just happen automatically.


> More specifically, as I have lots of threads use an isolate and then
> terminate, their Isolate::PerIsolateThreadData remains queued off
> of Isolate::ThreadDataTable list_. While this is essentially a memory leak,
> even worse, the queue just gets crazy long and the master (so first Isolate
> user) thread's Isolate::PerIsolateThreadData (being at the end) takes crazy
> long to find. And the entire massive queue has to be scanned each time a
> new thread uses the Isolate to determine that the thread does not yet have
> an Isolate::PerIsolateThreadData. Eventually v8 ends up spending most of
> its time scanning the Isolate::PerIsolateThreadData queue.
>

Yes.


> The solution would be to be able to get to
> Isolate::ThreadDataTable::Remove for defunct threads but I didn't see a
> path there from any embedder API functions. Is there one? And it looks like
> might be a few other thread-specific bits and bobs that might be left
> laying around, anyway.
>
> Maybe v8 just isn't built with apps that steadily create and destroy
> thread's in mind and such apps should just use their own thread pool
> managers and avoid allowing threads to terminate?
>

Precisely.

I think we would probably accept a patch (as long as it's not overly
intrusive) that adds the ability to discard thread-specific data. It's just
never been high enough on our priority list, because as you already said,
embedders can easily employ a thread pool to get by.


> Easy enough to do that though it's even easier if we don't have to -- the
> overhead of creating and joining threads is pretty tiny these days,
> especially relative to the "real work" that likely happens on each thread.
>
> 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.
> For more options, visit https://groups.google.com/d/optout.
>

-- 
-- 
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.
For more options, visit https://groups.google.com/d/optout.


Re: [v8-users] performance oddities of v8 Arrays

2015-10-18 Thread Jakob Kummerow
On Sat, Oct 17, 2015 at 12:20 AM, Dmitry Orlov  wrote:

> Thanks Jacob!
>
> On 16 October 2015 at 13:56, Jakob Kummerow 
> wrote:
>
>> It's not about what the "internal array representation" is, it's about
>> how the array is accessed. V8 employs all sorts of smarts to make
>> JavaScript execution very fast, because that's its job. Accessing things
>> via the C++ API ("array->Set(...)" in your example) isn't anywhere near as
>> optimized. The difference is most pronounced for tight hot loops, it will
>> be much smaller (to the point of being negligible) for code that runs only
>> once.
>>
> Is there any way to bulk-allocate a v8::Array in a cheap way, for example,
> from a C-array of v8::Handles?
>

The fastest way to exchange large amounts of data between C++ and JS is
probably an externalized

ArrayBuffer,
which allows access to its raw backing store on the C++ side, and a
TypedArray on top of it on the JS side.


> That said, if "Build Type: DEBUG" in your output means what I think it
>> means, then any performance measurement results are pretty much
>> meaningless. Try again in Release mode.
>>
> This message is reported because the Google benchmark library was build
> without NDEBUG directive:
>
> https://github.com/google/benchmark/blob/cf40a0f1172afc061e910eb5590f71e6ffdece66/src/console_reporter.cc#L43
> Apparently, that is the way its Makefile is written.
>
> My code is compiled wtih -O3:
> CXXFLAGS=-Wall -Werror -g -O3 -march=corei7 -mtune=corei7-avx -std=gnu++0x
> -pthread
>
> Is it possible that I inadvertently built V8 in debug mode? This is how I
> install it:
> $ export PATH=$PATH:/path/to/depot_tools
> $ fetch v8
> $ cd v8
> $ git fetch
> $ git checkout 4.2.77.21
>

You should update, 4.2 is outdated and unmaintained. branch-heads/4.6 is a
good choice right now (tip of the branch that's used in Chrome's Stable
channel).


> $ gclient sync
> $ make clean
> $ make -j8 native
>

OK, "make native" builds V8 in Release mode.


>
>> On Fri, Oct 16, 2015 at 8:57 PM, Dmitry Orlov 
>> wrote:
>>
>>> Hello everyone,
>>>
>>> I've noticed peculiar performance characteristics of V8 objects when
>>> benchmarking my V8-embedding application. In particular, v8::Array is
>>> incredibly expensive - each Set(index, value) operation on an array
>>> consistently takes 100ns on a 3.4Ghz Xeon, instead of single digit
>>> nanoseconds one would expect from a C-array based implementation.
>>> In contrast, javascript code using arrays runs blaze-fast, taking around
>>> 2ns for each assignment.
>>>
>>> I've benchmarked these code fragments separately, implementation is
>>> below:
>>>
>>> void allocate_v8_integer_array(benchmark::State& state) {
>>> v8::HandleScope scope(isolate);
>>> v8::Local int_value = v8::Integer::New(isolate, 100);
>>> while (state.KeepRunning()) {
>>> const int n = state.range_x();
>>> v8::Local array = v8::Array::New(isolate,
>>> state.range_x());
>>> for (int i = 0; i < n; ++i) {
>>> array->Set(i, int_value);
>>> }
>>> }
>>> }
>>>
>>> void allocate_v8_integer_array_in_javascript(benchmark::State& state) {
>>> v8::TryCatch try_catch(isolate);
>>> v8::HandleScope scope(isolate);
>>> v8::Local script =
>>> v8::Script::Compile(v8::String::NewFromUtf8(isolate,
>>> "function run(n) {"
>>> "  var x = Array(n);"
>>> "  for (var i = 0; i < n; i++) {"
>>> "x[i] = i;"
>>> "  }"
>>> "}"));
>>> script->Run();
>>> assert(!try_catch.HasCaught());
>>> v8::Local run = v8::Local::Cast(
>>>
>>> context.Get(isolate)->Global()->Get(v8::String::NewFromUtf8(isolate,
>>> "run")));
>>> v8::Local arg = v8::Integer::New(isolate,
>>> state.range_x());
>>> while (state.KeepRunning()) {
>>> run->Call(context.Get(isolate)->Global(), 1, );
>>> assert(!try_catch.HasCaught());
>>> }
>>> }
>>>
>>> Benchmark results:
>>> Run on (8 X 3399.98 MHz CPU s
>>> 2015-10-16 18:47:44
>>> Build Type: DEBUG
>>> Benchmark  Time(ns)CPU(ns)
>>> Iterations
>>>
>>> -
>>> allocate_v8_integer_array/1 190190
>>>  3688287
>>> allocate_v8_integer_array/10   1061   1061
>>>   659836
>>> allocate_v8_integer_array/100  9936   9930
>>>70495
>>> allocate_v8_integer_array/100096517  96458
>>> 7259
>>> allocate_v8_integer_array/9.76562k   967739 967146
>>>  724
>>> allocate_v8_integer_array_in_javascript/10  487486
>>>  3104447
>>> allocate_v8_integer_array_in_javascript/1001075   1074
>>>  100
>>> 

[v8-users] Track script execution start and stop.

2015-10-18 Thread Bogdan Padalko
Hi, I'm embedding v8 and have to limit max time that arbitrary script 
execution may take. 

As to script running complete event, it is more or less clear - 
v8::Isolate::AddCallCompletedCallback() will do the job, but as to catching 
start I'm stuck a bit. There is v8::Isolate::SetEventLogger() which also 
may do the job, callback receives event name and start/end flag, so I can 
strcmp() event name (the target one is V8.Execute) and track it in this 
way, but maybe there are nicer solution, like 
v8::Isolate::AddCallCompletedCallback() but for start, not complete?

Without hook, one have track any possible execution points, (not only 
v8::ScriptRun() but also v8::Value::ToString, v8::Function::Call and so 
on), which may lead to some missed execution point.

-- 
-- 
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.
For more options, visit https://groups.google.com/d/optout.


Re: [v8-users] Thread cleanup

2015-10-18 Thread Alex Kodat
Jakob,

Thanks for that. I might just take a swing at an unintrusive patch. Along 
those lines it seems that thread resource cleanup would be closely tied to 
the Locker as one would need the isolate lock while freeing 
PerIsolateThreadData but would presumably want to release the lock 
immediately after. So it seems the most logical approach would be a Locker 
class variable called say cleanup_ that's set either with an extra 
parameter on the Locker constructor or a Locker method to clean up at 
destruction time (both with appropriate semantics if not top_level_ or 
has_lock_).

But just want to make sure that this couldn't be even made less intrusive 
by just always cleaning up if top_level_ and has_lock_ in the Locker 
destructor. As it is, in this case ThreadManager::FreeThreadResources ends 
up being called which doesn't seem to leave a heck a lot of useful stuff 
around for the thread so leaving a few crumbs around seems mainly an 
efficiency issue -- if someone has a lot of top level Locker brackets in a 
loop, there might be a bit of extra object creation/destruction if 
ThreadManager::FreeThreadResources always does a full thread cleanup but 
it's hard to imagine that being significant for anyone. In the unlikely 
event that it is, an embedder can create an outer Locker with nested 
Unlockers, an approach that would have no v8 release dependencies. 

So which approach would you prefer: just do it, Locker class method, or 
Locker constructor parameter?

Thanks 

On Sunday, October 18, 2015 at 4:07:07 AM UTC-7, Jakob Kummerow wrote:
>
> On Sun, Oct 18, 2015 at 8:16 AM, Alex Kodat  > wrote:
>
>> If I have an app that steadily creates and joins threads, is there a good 
>> way of cleaning up the thread-specific data when a thread terminates? 
>> Looking at the v8 code, it seems that ThreadManager::FreeThreadResources in 
>> v8threads.cc would be a place this might happen when called from the Locker 
>> destructor when top_level_ is set. But maybe for good reason not all 
>> thread-specific data seems to be cleaned up?
>>
>
> Just because a thread releases a lock doesn't mean that thread is about to 
> die. It might come back to V8 later. So any cleanup would have to be 
> triggered explicitly by the embedder, it can't just happen automatically.
>  
>
>> More specifically, as I have lots of threads use an isolate and then 
>> terminate, their Isolate::PerIsolateThreadData remains queued off 
>> of Isolate::ThreadDataTable list_. While this is essentially a memory leak, 
>> even worse, the queue just gets crazy long and the master (so first Isolate 
>> user) thread's Isolate::PerIsolateThreadData (being at the end) takes crazy 
>> long to find. And the entire massive queue has to be scanned each time a 
>> new thread uses the Isolate to determine that the thread does not yet have 
>> an Isolate::PerIsolateThreadData. Eventually v8 ends up spending most of 
>> its time scanning the Isolate::PerIsolateThreadData queue. 
>>
>
> Yes.
>  
>
>> The solution would be to be able to get to 
>> Isolate::ThreadDataTable::Remove for defunct threads but I didn't see a 
>> path there from any embedder API functions. Is there one? And it looks like 
>> might be a few other thread-specific bits and bobs that might be left 
>> laying around, anyway.
>>
>> Maybe v8 just isn't built with apps that steadily create and destroy 
>> thread's in mind and such apps should just use their own thread pool 
>> managers and avoid allowing threads to terminate? 
>>
>
> Precisely.
>
> I think we would probably accept a patch (as long as it's not overly 
> intrusive) that adds the ability to discard thread-specific data. It's just 
> never been high enough on our priority list, because as you already said, 
> embedders can easily employ a thread pool to get by.
>  
>
>> Easy enough to do that though it's even easier if we don't have to -- the 
>> overhead of creating and joining threads is pretty tiny these days, 
>> especially relative to the "real work" that likely happens on each thread. 
>>
>> Thanks
>>
>> -- 
>> -- 
>> 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+u...@googlegroups.com .
>> For more options, visit https://groups.google.com/d/optout.
>>
>
>

-- 
-- 
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.
For more options, visit https://groups.google.com/d/optout.