Haxe/v8 performance

classic Classic list List threaded Threaded
14 messages Options
Reply | Threaded
Open this post in threaded view
|

Haxe/v8 performance

Gamehaxe
Hi,

After writing a little mail here about JS performance, I decided to try it  
out.
The google v8 library has some quite nice embedding options, and the hxcpp
plugins have been written is such a way that should be able to be used by
most scripting systems.  It turns out that only a minor modification was
required to get a v8-vm running with haxe generated js.

You can see more about this here:

http://gamehaxe.com/2010/05/25/javascript-ready-or-not/

Hugh

--
haXe - an open source web programming language
http://haxe.org
Reply | Threaded
Open this post in threaded view
|

Re: Haxe/v8 performance

alstrup
Hi,

Nice hack. How hard is it to bind external libraries, such as MySQL, or even reuse somehow hook it up to use existing Neko libraries? Looking at the performance numbers, it seems to beat the Neko target handily. 

(Incidentally, the Neko LLVM backend is now about the double speed of Neko interpreter for long running, simple calculation loops and other simple things, but still slower for most other things.)

Regards,
Asger


--
haXe - an open source web programming language
http://haxe.org
Reply | Threaded
Open this post in threaded view
|

Re: Haxe/v8 performance

Nicolas Cannasse
Asger Ottar Alstrup a écrit :
> Hi,
>
> Nice hack. How hard is it to bind external libraries, such as MySQL, or
> even reuse somehow hook it up to use existing Neko libraries? Looking at
> the performance numbers, it seems to beat the Neko target handily.

Just a small thing : physaxe rely heavily one float calculus, which Neko
is known to be slow for, since double values are boxed : each arithmetic
operation allocate a new memory block which need to be handled by the GC.

Nicolas

--
haXe - an open source web programming language
http://haxe.org
Reply | Threaded
Open this post in threaded view
|

Haxe/v8 (& neko) performance

Gamehaxe
Yes, that will hurt.
I like neko for what it is - very fast to generate, small foot print,
cross platform dynamic machine.

There has been some talk of optimizing neko, but I guess I'm questioning
the goal of the project.  Is it just to get a 2x faster vm?  If so, the
*easiest* way, IMHO, may be to use v8 as the backend and call it done.
This would require the neko ndlls to be re-written to be more like
the cpp ones - which would please me if they were unified.
Also, the GC is not conservative, so some co-operation would be required.
That said, if goal is just to pick some "low hanging fruit" then fair  
enough.

Another option I see would be to start a "high performance vm".  This
would use the same "typing strength" as the current c++ target
(it could also use the same libs).
Maybe it would generate llvm, or maybe bytecode, which can then JITed.
This would retain the benefits of the dynamic typing, but also
allow high performance.  I see the performance of this being similar
the the JVM, which I guess is about 2x flash speed, 4x JS, 10x neko
or maybe 60% cpp speed. But with the advantage of begin cross-platform.
Thinking about the c++ runtime & virtual table layout, I think the vm  
practically
designs itself.

A final option would be to target java for similar benefits - although
the installation of java is not nearly as nice as neko.

Some food for thought.

Hugh



> Asger Ottar Alstrup a écrit :
>> Hi,
>>  Nice hack. How hard is it to bind external libraries, such as MySQL,  
>> or even reuse somehow hook it up to use existing Neko libraries?  
>> Looking at the performance numbers, it seems to beat the Neko target  
>> handily.
>
> Just a small thing : physaxe rely heavily one float calculus, which Neko  
> is known to be slow for, since double values are boxed : each arithmetic  
> operation allocate a new memory block which need to be handled by the GC.
>
> Nicolas

--
haXe - an open source web programming language
http://haxe.org
Reply | Threaded
Open this post in threaded view
|

Re: Haxe/v8 (& neko) performance

alstrup
Hi,

The goal of the LLVM work is to get a faster *production quality* Neko in a relatively short time frame, including support for existing neko libs. hxcpp has been under development for a long time, and is 90%. We need 99% before it will work for us. This also kills the v8 idea, because the Neko libs are not available for that. (We did port try to MySQL and some other libs to hxcpp, but it takes a long time, and it was hard to get production quality. Maybe this is simpler with v8 - I would like to hear your thought on that.) Starting a completely new backend would also take a long time.

LLVM for Neko seems like the shortest way forward for us. Perfect is the enemy of good. LLVM seems to give a factor of 2 for now, and that is important to us. Of course, we hope it will be better. And once we have a working LLVM backend, maybe Nicolas will tune the neko bytecode to expose more static typing as another approach to get more speed.

If someone can do a production quality, fast 99% complete new haXe backend with support for existing neko libs in some other way, I will be happy to learn about it.

Regards,
Asger


--
haXe - an open source web programming language
http://haxe.org
Reply | Threaded
Open this post in threaded view
|

Re: Haxe/v8 (& neko) performance

Nicolas Cannasse
Asger Ottar Alstrup a écrit :
> LLVM for Neko seems like the shortest way forward for us. Perfect is the
> enemy of good. LLVM seems to give a factor of 2 for now, and that is
> important to us. Of course, we hope it will be better. And once we have
> a working LLVM backend, maybe Nicolas will tune the neko bytecode to
> expose more static typing as another approach to get more speed.

I agree with that approach. I think that NekoVM has a good speed/load
balance, but in some cases you want something to be able to crush
numbers a lot faster.

Having access to such optimized VM without switching your technology
stack and being able to run all your existing codebase without any
recompilation on such VM would be great.

I'm not sure which kind of speed multiplier we can get when the LLVM
backend is done for the current VM, but this is a good step towards
adding type annotations to neko functions which will lead to further
optimizations.

Nicolas

--
haXe - an open source web programming language
http://haxe.org
Reply | Threaded
Open this post in threaded view
|

Re: Haxe/v8 (& neko) performance

tommedema
I am very interested in a faster Neko VM. I'm personally writing a server application for it for a massive multiplayer game. Unfortunately a lot of positional data has to be calculated server side, and neko doesn't seem to be the fastest when it comes to calculations.

This is also why I have been looking into the cpp target. Unfortunately, it does not seem to be used that much, and there are problems when you want to work with utlities like MySQL. I personally have no idea how one would implement MySQL to the CPP target. I know one can add certain c libraries, but how, and what amount of experience is needed for it, I'm not sure.

Regards,
Tom

2010/5/26 Nicolas Cannasse <[hidden email]>
Asger Ottar Alstrup a écrit :
LLVM for Neko seems like the shortest way forward for us. Perfect is the enemy of good. LLVM seems to give a factor of 2 for now, and that is important to us. Of course, we hope it will be better. And once we have a working LLVM backend, maybe Nicolas will tune the neko bytecode to expose more static typing as another approach to get more speed.

I agree with that approach. I think that NekoVM has a good speed/load balance, but in some cases you want something to be able to crush numbers a lot faster.

Having access to such optimized VM without switching your technology stack and being able to run all your existing codebase without any recompilation on such VM would be great.

I'm not sure which kind of speed multiplier we can get when the LLVM backend is done for the current VM, but this is a good step towards adding type annotations to neko functions which will lead to further optimizations.


Nicolas

--
haXe - an open source web programming language
http://haxe.org


--
haXe - an open source web programming language
http://haxe.org
Reply | Threaded
Open this post in threaded view
|

Re: Haxe/v8 (& neko) performance

Fabien Bourgeois
Hugh Sanderson a écrit :

 > Another option I see would be to start a "high performance vm".  This
 > would use the same "typing strength" as the current c++ target
 > (it could also use the same libs).

Another option *might* be a Lua target. There was an old try on
Caffeine[1] and Lua-JIT seems to be one of the fastest JIT
implemented[2] for a dynamic-typed language - maybe as fast as Java
against a small memory usage increase[3].

Lua seems to have several ways[4] to bind C/C++ code but it may hurts
the JITed performance [5].

Having said that, I agree with Nicolas and Tom. It may be awesome to
improve Neko performance through LLVM.

1 : [http://code.google.com/p/caffeine-hx/]
2 : [http://shootout.alioth.debian.org/fastest-programming-language.php]
, [http://luajit.org/performance.html]
3 :
[http://shootout.alioth.debian.org/u64/benchmark.php?test=all&lang=luajit&lang2=lua]
4 : [http://lua-users.org/wiki/BindingCodeToLua]
5 :
[http://stackoverflow.com/questions/2588071/is-luajit-really-faster-than-every-other-jit-ed-dynamic-languages]

--
haXe - an open source web programming language
http://haxe.org
Reply | Threaded
Open this post in threaded view
|

Re: Haxe/v8 (& neko) performance

Gamehaxe
In reply to this post by alstrup
Hi Asger,
As far as library porting to v8 - the libraries are identical to the cpp
libraries. The exact same NME.ndll file is being used by neko, cpp & v8vm
in the binary demo at  
http://gamehaxe.com/wp-content/physaxe/physaxe-win32.zip

I think you can choose to make your libraries for neko, or you can choose
to make them for everything (ie, for a java target too, if it should come  
along -
I'm waiting for someone to start an android port) with only a little  
effort.
Infact, it should not be that much extra effort.

I'm not sure of the nature of the problems you have experienced porting
mysql, but attacking this part may be easier than a complete vm re-write.
Using c++ and macros, you can churn out the interface files once you get  
going.

I would really like to see all NDLL files moving towards a standard that
is target agnostic.  This would also help spread the load for a single
developer writing a target, also having to support all the libraries.

For example, if in neko version 2, you want to change the structure
to allow, say, 32 bit ints, you will need to recompile all the NDLLs
unless you move to an agnostic handle based API.

Hugh

> Hi,
>
> The goal of the LLVM work is to get a faster *production quality* Neko  
> in a
> relatively short time frame, including support for existing neko libs.  
> hxcpp
> has been under development for a long time, and is 90%. We need 99%  
> before
> it will work for us. This also kills the v8 idea, because the Neko libs  
> are
> not available for that. (We did port try to MySQL and some other libs to
> hxcpp, but it takes a long time, and it was hard to get production  
> quality.
> Maybe this is simpler with v8 - I would like to hear your thought on
> that.) Starting a completely new backend would also take a long time.
>
> LLVM for Neko seems like the shortest way forward for us. Perfect is the
> enemy of good. LLVM seems to give a factor of 2 for now, and that is
> important to us. Of course, we hope it will be better. And once we have a
> working LLVM backend, maybe Nicolas will tune the neko bytecode to expose
> more static typing as another approach to get more speed.
>
> If someone can do a production quality, fast 99% complete new haXe  
> backend
> with support for existing neko libs in some other way, I will be happy to
> learn about it.
>
> Regards,
> Asger

--
haXe - an open source web programming language
http://haxe.org
Reply | Threaded
Open this post in threaded view
|

Re: Haxe/v8 (& neko) performance

Philipp Klose-2
Hugh Sanderson wrote:
>
> I would really like to see all NDLL files moving towards a standard that
> is target agnostic.  This would also help spread the load for a single
> developer writing a target, also having to support all the libraries.
I also loved to have generic ndll. A few days ago tried to archive this
with a few of my ndll but for the cpp target is quite hard, because
there is quite no documentation. Especially accessing objects seems to
be totally different from the neko target. It would be nice if the
website would more documentation about how to port a ndll to the cpp target.


--
haXe - an open source web programming language
http://haxe.org
Reply | Threaded
Open this post in threaded view
|

Re: Haxe/v8 (& neko) performance

Gamehaxe
Hi,
The process should be pretty much the same.

For some doco in the differences, see:
http://haxe.org/doc/cpp/ffi

For a (big) example, see:

http://code.google.com/p/nekonme/source/browse/trunk/version2/project/common/ExternalInterface.cpp

Which has snippets like:


static int _id_x = val_id("x");
static int _id_y = val_id("y");
...
...


void FromValue(DRect &outRect, value inValue)
{
    if (val_is_null(inValue))
       return;
    outRect.x = val_field_numeric(inValue,_id_x);
    outRect.y = val_field_numeric(inValue,_id_y);
    outRect.w = val_field_numeric(inValue,_id_width);
    outRect.h = val_field_numeric(inValue,_id_height);
}

where "val_field_numeric" is a shortcut for "val_number(val_field)", as in:


void FromValue(SoundTransform &outTrans, value inValue)
{
    if (!val_is_null(inValue))
    {
        outTrans.volume = val_number( val_field(inValue,_id_volume) );
        outTrans.pan = val_number( val_field(inValue,_id_pan) );
    }
}

But allows for a high-performance option that avoids boxing if possible
(or falls back the default implementation).

I have found a nice design pattern - which would work for pure neko too -
where you define a single "abstract kind", and then derive your GC objects
 from this, and then use dynamic_cast to get it back.  With the
internal reference counting, this makes adding new "managed types" very  
easy.

eg:


value nme_get_frame_stage(value inValue)
{
    Frame *frame;
    if (!AbstractToObject(inValue,frame))
       return alloc_null();


    return ObjectToAbstract(frame->GetStage());
}
DEFINE_PRIM(nme_get_frame_stage,1);

where "Frame" and "Stage" inherits from my base "Object".
Object also has reference counting, so the abstract holds a ref on the
Object - but you can have additional internal ones.  The external ones
use garbage collection, so circular references are fine in the haxe code,
but you have to be a little careful of them in the ndll code.

Here "AbstractToObject" is doing a dynamic_cast.

Hugh



> Hugh Sanderson wrote:
>>
>> I would really like to see all NDLL files moving towards a standard that
>> is target agnostic.  This would also help spread the load for a single
>> developer writing a target, also having to support all the libraries.
> I also loved to have generic ndll. A few days ago tried to archive this  
> with a few of my ndll but for the cpp target is quite hard, because  
> there is quite no documentation. Especially accessing objects seems to  
> be totally different from the neko target. It would be nice if the  
> website would more documentation about how to port a ndll to the cpp  
> target.
>

--
haXe - an open source web programming language
http://haxe.org
Reply | Threaded
Open this post in threaded view
|

Re: Haxe/v8 (& neko) performance

Andy Li
For using cffi, I'm experimenting auto generate those ndll and haXe classes with the help of gccxml, which can output the C++ header in xml format. (for anyone want to try gccxml, remember to use its cvs version...)

And some time ago I found libffi, seems to be a nice thing if it is integrated into the haXe core. And maybe we can directly use dll without compiling another ndll?

Cheers,
Andy

On Thu, May 27, 2010 at 12:36 AM, Hugh Sanderson <[hidden email]> wrote:
Hi,
The process should be pretty much the same.

For some doco in the differences, see:
http://haxe.org/doc/cpp/ffi

For a (big) example, see:

http://code.google.com/p/nekonme/source/browse/trunk/version2/project/common/ExternalInterface.cpp

Which has snippets like:


static int _id_x = val_id("x");
static int _id_y = val_id("y");
...
...


void FromValue(DRect &outRect, value inValue)
{
  if (val_is_null(inValue))
     return;
  outRect.x = val_field_numeric(inValue,_id_x);
  outRect.y = val_field_numeric(inValue,_id_y);
  outRect.w = val_field_numeric(inValue,_id_width);
  outRect.h = val_field_numeric(inValue,_id_height);
}

where "val_field_numeric" is a shortcut for "val_number(val_field)", as in:


void FromValue(SoundTransform &outTrans, value inValue)
{
  if (!val_is_null(inValue))
  {
      outTrans.volume = val_number( val_field(inValue,_id_volume) );
      outTrans.pan = val_number( val_field(inValue,_id_pan) );
  }
}

But allows for a high-performance option that avoids boxing if possible
(or falls back the default implementation).

I have found a nice design pattern - which would work for pure neko too -
where you define a single "abstract kind", and then derive your GC objects
from this, and then use dynamic_cast to get it back.  With the
internal reference counting, this makes adding new "managed types" very easy.

eg:


value nme_get_frame_stage(value inValue)
{
  Frame *frame;
  if (!AbstractToObject(inValue,frame))
     return alloc_null();


  return ObjectToAbstract(frame->GetStage());
}
DEFINE_PRIM(nme_get_frame_stage,1);

where "Frame" and "Stage" inherits from my base "Object".
Object also has reference counting, so the abstract holds a ref on the
Object - but you can have additional internal ones.  The external ones
use garbage collection, so circular references are fine in the haxe code,
but you have to be a little careful of them in the ndll code.

Here "AbstractToObject" is doing a dynamic_cast.

Hugh




Hugh Sanderson wrote:

I would really like to see all NDLL files moving towards a standard that
is target agnostic.  This would also help spread the load for a single
developer writing a target, also having to support all the libraries.
I also loved to have generic ndll. A few days ago tried to archive this with a few of my ndll but for the cpp target is quite hard, because there is quite no documentation. Especially accessing objects seems to be totally different from the neko target. It would be nice if the website would more documentation about how to port a ndll to the cpp target.


--
haXe - an open source web programming language
http://haxe.org


--
haXe - an open source web programming language
http://haxe.org
Reply | Threaded
Open this post in threaded view
|

Re: Haxe/v8 (& neko) performance

Philipp Klose-2
In reply to this post by Gamehaxe
Thank you Hugh for this input. Know everything is a lot clearer to me.
There are still a few thing I am not sure about:

What is the replacement for "val_iter_field" or how could I get all
field of an anonymous object?
"val_id" gives the integer has for a fieldname. Using the neko CFFI you
could use "val_field_name" to do the reverse? Is this also possible for
the cpp FFI?

Thank.

Philipp

Hugh Sanderson wrote:

> Hi,
> The process should be pretty much the same.
>
> For some doco in the differences, see:
> http://haxe.org/doc/cpp/ffi
>
> For a (big) example, see:
>
> http://code.google.com/p/nekonme/source/browse/trunk/version2/project/common/ExternalInterface.cpp 
>
>
> Which has snippets like:
>
>
> static int _id_x = val_id("x");
> static int _id_y = val_id("y");
> ...
> ...
>
>
> void FromValue(DRect &outRect, value inValue)
> {
>    if (val_is_null(inValue))
>       return;
>    outRect.x = val_field_numeric(inValue,_id_x);
>    outRect.y = val_field_numeric(inValue,_id_y);
>    outRect.w = val_field_numeric(inValue,_id_width);
>    outRect.h = val_field_numeric(inValue,_id_height);
> }
>
> where "val_field_numeric" is a shortcut for "val_number(val_field)",
> as in:
>
>
> void FromValue(SoundTransform &outTrans, value inValue)
> {
>    if (!val_is_null(inValue))
>    {
>        outTrans.volume = val_number( val_field(inValue,_id_volume) );
>        outTrans.pan = val_number( val_field(inValue,_id_pan) );
>    }
> }
>
> But allows for a high-performance option that avoids boxing if possible
> (or falls back the default implementation).
>
> I have found a nice design pattern - which would work for pure neko too -
> where you define a single "abstract kind", and then derive your GC
> objects
> from this, and then use dynamic_cast to get it back.  With the
> internal reference counting, this makes adding new "managed types"
> very easy.
>
> eg:
>
>
> value nme_get_frame_stage(value inValue)
> {
>    Frame *frame;
>    if (!AbstractToObject(inValue,frame))
>       return alloc_null();
>
>
>    return ObjectToAbstract(frame->GetStage());
> }
> DEFINE_PRIM(nme_get_frame_stage,1);
>
> where "Frame" and "Stage" inherits from my base "Object".
> Object also has reference counting, so the abstract holds a ref on the
> Object - but you can have additional internal ones.  The external ones
> use garbage collection, so circular references are fine in the haxe code,
> but you have to be a little careful of them in the ndll code.
>
> Here "AbstractToObject" is doing a dynamic_cast.
>
> Hugh
>
>
>
>> Hugh Sanderson wrote:
>>>
>>> I would really like to see all NDLL files moving towards a standard
>>> that
>>> is target agnostic.  This would also help spread the load for a single
>>> developer writing a target, also having to support all the libraries.
>> I also loved to have generic ndll. A few days ago tried to archive
>> this with a few of my ndll but for the cpp target is quite hard,
>> because there is quite no documentation. Especially accessing objects
>> seems to be totally different from the neko target. It would be nice
>> if the website would more documentation about how to port a ndll to
>> the cpp target.
>>
>


--
haXe - an open source web programming language
http://haxe.org
Reply | Threaded
Open this post in threaded view
|

Re: Haxe/v8 (& neko) performance

Gamehaxe
Hi Philpp,

These methods seem to be missing - I'll add them for the next release.

Hugh

> Thank you Hugh for this input. Know everything is a lot clearer to me.
> There are still a few thing I am not sure about:
>
> What is the replacement for "val_iter_field" or how could I get all  
> field of an anonymous object?
> "val_id" gives the integer has for a fieldname. Using the neko CFFI you  
> could use "val_field_name" to do the reverse? Is this also possible for  
> the cpp FFI?
>
> Thank.
>
> Philipp
>
> Hugh Sanderson wrote:
>> Hi,
>> The process should be pretty much the same.
>>
>> For some doco in the differences, see:
>> http://haxe.org/doc/cpp/ffi
>>
>> For a (big) example, see:
>>
>> http://code.google.com/p/nekonme/source/browse/trunk/version2/project/common/ExternalInterface.cpp 
>> Which has snippets like:
>>
>>
>> static int _id_x = val_id("x");
>> static int _id_y = val_id("y");
>> ...
>> ...
>>
>>
>> void FromValue(DRect &outRect, value inValue)
>> {
>>    if (val_is_null(inValue))
>>       return;
>>    outRect.x = val_field_numeric(inValue,_id_x);
>>    outRect.y = val_field_numeric(inValue,_id_y);
>>    outRect.w = val_field_numeric(inValue,_id_width);
>>    outRect.h = val_field_numeric(inValue,_id_height);
>> }
>>
>> where "val_field_numeric" is a shortcut for "val_number(val_field)", as  
>> in:
>>
>>
>> void FromValue(SoundTransform &outTrans, value inValue)
>> {
>>    if (!val_is_null(inValue))
>>    {
>>        outTrans.volume = val_number( val_field(inValue,_id_volume) );
>>        outTrans.pan = val_number( val_field(inValue,_id_pan) );
>>    }
>> }
>>
>> But allows for a high-performance option that avoids boxing if possible
>> (or falls back the default implementation).
>>
>> I have found a nice design pattern - which would work for pure neko too  
>> -
>> where you define a single "abstract kind", and then derive your GC  
>> objects
>> from this, and then use dynamic_cast to get it back.  With the
>> internal reference counting, this makes adding new "managed types" very  
>> easy.
>>
>> eg:
>>
>>
>> value nme_get_frame_stage(value inValue)
>> {
>>    Frame *frame;
>>    if (!AbstractToObject(inValue,frame))
>>       return alloc_null();
>>
>>
>>    return ObjectToAbstract(frame->GetStage());
>> }
>> DEFINE_PRIM(nme_get_frame_stage,1);
>>
>> where "Frame" and "Stage" inherits from my base "Object".
>> Object also has reference counting, so the abstract holds a ref on the
>> Object - but you can have additional internal ones.  The external ones
>> use garbage collection, so circular references are fine in the haxe  
>> code,
>> but you have to be a little careful of them in the ndll code.
>>
>> Here "AbstractToObject" is doing a dynamic_cast.
>>
>> Hugh
>>
>>
>>
>>> Hugh Sanderson wrote:
>>>>
>>>> I would really like to see all NDLL files moving towards a standard  
>>>> that
>>>> is target agnostic.  This would also help spread the load for a single
>>>> developer writing a target, also having to support all the libraries.
>>> I also loved to have generic ndll. A few days ago tried to archive  
>>> this with a few of my ndll but for the cpp target is quite hard,  
>>> because there is quite no documentation. Especially accessing objects  
>>> seems to be totally different from the neko target. It would be nice  
>>> if the website would more documentation about how to port a ndll to  
>>> the cpp target.
>>>
>>
>

--
haXe - an open source web programming language
http://haxe.org