On Thu, Oct 29, 2015 at 11:07 AM, Ben N <lazydo...@mac.com> wrote:
> Hi
>
> I am just starting out with V8 and I'm slowly finding my way round it but I
> have run into a problem. I'm sorry if this is a common question or if the
> answer is obvious, but I have spent some time trying to Google it and I
> haven't found a satisfactory explanation.
>
> The problem I have concerns the speed of calling a JavaScript function from
> C++  which is very very slow. Compared to calling the same function from
> JavaScript I"m finding it roughly 400 times slower. I've created a simple
> function which highlights this speed difference and the code is below.
>
> Any advice on how fix this speed issue  would be very much appreciated.  I'm
> developing on a Mac and Xcode by the way.
>
> thank you and apologies if I'm asking or doing anything dumb!
>
> b e n
>
>
> This is what I have on the JavaScript side:
>
> var raycast_count ;
> var raytracer = new kraytracer() ;
>
> raytracer.oncastray = function( x, y )
> {
>    ++ raycast_count ;
>   return true ;
> }
>
> // this loop takes about 0.03 seconds to run
> raycast_count = 0 ;
> for ( var j = 0 ; j < 1980 ; ++j )
>    for ( var i = 0 ; i < 1440 ; ++ i )
>      raytracer.oncastray( i, j ) ;
>
>
> // raytracer.begin() is C++ function that performs the same loop above.
> // It takes 13 seconds though!
> raycast_count = 0 ;
> raytracer.begin() ;
>
>
>
> and on the C++ side I have a callback for raytracer.begin() which looks
> roughly like this,
>
> void v8raytracer::begin( const FunctionCallbackInfo<Value> & info )
> {
>  ...
>  ...
>
> Local<Value> oncastray = info.This()->Get( String::NewFromUtf8( isolate,
> "oncastray" ) ) ;
>  Handle<Value> parameters[ 2 ] ;
>  Local<Value> rcv = info.This() ;
>
>  if ( oncastray->IsFunction() )
>  {
>    Local<Function> oncastray_fn = Handle<Function>::Cast( oncastray ) ;
>
>    for ( int j = 0 ; j < 1980 ; ++j )
>       for ( int i = 0 ; i < 1440 ; ++i )
>       {
>           parameters[ 0 ] = Integer::New( isolate, x ) ;
>           parameters[ 1 ] = Integer::New( isolate, y ) ;
>
>            oncastray_fn->Call( rcv, 2, parameters ) ;
>       }
>   }
>  ...
>  ...
> }

The short answer is to keep the number of C++ -> JS transitions to a
minimum.  If you look at the call stack in a debugger, you'll see why
it's so much slower: V8 has to insert a couple of adapter frames that
convert between the JS and C++ calling conventions.  (Also, it can't
inline the function body like it does for hot JS functions.)

In most cases, the easiest solution is to batch arguments: instead of
calling a native function ten times with one argument, call it one
time with ten arguments.  Look into using typed arrays for passing
data, they're cheaper to inspect in C++ land than regular JS arrays;
v8::Array::Get() is quite slow.

-- 
-- 
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.

Reply via email to