From native code to browser: Flash, Haxe, Dart or asm.js?
infognition.com
infognition.com
I think Haxe is underappreciated for areas other than game development. You can write serverside logic with it (compile to js for node.js, php, neko, java, c#, python), and target flash and js in the browser.
I used it extensively at Chumby on apps for the devices since the alternative was using ActionScript 2 (which is basically JavaScript minus the more modern features post-ECMAScript3).
Given roughly the same code (minus the syntax differences for each), the Haxe compiler would run much faster than Adobe's and almost always generated faster bytecode even though I was targeting Adobe's own Flash AVM1. Plus haxe let me use all the goodies the language offers, like non-brain-dead scoping, static typing and the macro system.
http://blog.puzzlingplans.com/post/100992521086/building-a-c...
Sublime text makes a nice(ish) IDE with free plugins.
Additionally, we can relatively easily compile out iOS and Android binaries should we want/need to. It's a very nice system to work with and has caused us very little problems with just getting things done.
But I never understood why native android and ios games made in flambe require adobe air... OpenFL clearly wins in this regard.
Another option the author could have explored is js_of_ocaml. It compiles OCaml bytecode to JavaScript. It works quite well in my (somewhat limited) experience.
The author seems to have a bit of a bias (Dart's designers "ate too much Java for breakfast"), but Java is rock solid, and being able to write the entire application, from the client and the domain model on down to the backend, is a major boost. GWT also has a vibrant community (see f.ex. the GWT.create() event across US and Europe: http://gwtcreate.com/) and lots of invention and development going on, with a huge new release (2.7) coming up.
See my game project for an example of GWT in action: http://www.webworks.dk/html5engine
You can see a chart of size and performance here: https://plus.google.com/+BrandonDonnelson/posts/DSUgfWefyR3
GWT won on size across the board and beat everything but C on performance. Of course, this benchmark, like most, is biased. It uses a lot of polymorphism, and GWT does exceptionally well at removing polymorphic dispatch statically.
Are you sure? I have never looked at Java implementation of Box2D used in this benchmark, but Dart version is definitely not that polymorphic in its hottest function which corresponds to this Java one:
https://github.com/jbox2d/jbox2d/blob/76fa2602a6abcbc557c9d5...
It looks like mostly a bunch of floating point math to me with not that many calls out.
Another interesting thing I noticed now is that Java version has all vector math inlined manually, while in Dart version it is not the case (at least not entirely if I remember correctly - we want to write high level code and let optimizer do what it can).
The vector math does look like an apples-to-oranges comparisons. Simple methods like cross-product will inline in GWT as well. The biggie seems to be the elision of the temporary, we'd need something like C++'s return value optimization to get rid of that.
I'll try rerunning the bench by adding calls to cross-product to see how it fares. Actually for us, we weren't as interested in comparing the speed to Dart as much as comparing it to the JVM version. The slowdown there is on the order of 50% which isn't bad. In the original thread on G+ I noted there's no way this can be considered an apples-to-apples comparison because they're not running the same code (the port's from Box2D differ), but Joel's whole Box2D benchmark suite kind of rests on this.
btw, if you have a moment I would really appreciate if you tell me how to reproduce +Brandon Donnelson results. It's hard to figure out from those photos which version of GWT should I get from where and what to compile with it. I was not sure if I supposed to check out Joel's code AS IS or I should get it from some other place, etc.
Then you'll need my fork of Joel's repository here: https://github.com/cromwellian/bench2d
I'm not sure they were upstreamed into his.
Brandon's results were culled from the informal results I posted in Joel's G+ thread (which he independently verified). From the thread you can see I was quite disbelieving myself and not at all ready to plant a flag, I even implemented a verification in the GWT version to ensure that the final resting state of the system converged to what it was supposed to.
Some very tiny patches to GWT (adding dummy random unique properties to prototypes, an optimization to HashMap.put/ArrayList.get, etc) have lead to 300-500% speedups in our benchmark server, meanwhile really complex ones actually slowed things down, or did nothing.
For example, I added asmjs output to GWT (where possible in method bodies, not a truly strict-check), I also implemented an optimization which auto-converts Java classes to typedarrays where possible, e.g.
class Vec3 { float x, y, z; // getters and setters }
Would require the class into a bag of static methods and rewrite the field accesses into indexes into a typed array. This turned out not to be a win when benchmarked on Box2D, probably for other reasons.
:(
Converting classes into typed arrays/typed array buffers is something that seems like it should be awesome but in practice isn't. :( I've tried it extensively in JSIL as well and it seems to only be a win if you have thousands of them in an array - for individual instances you get murdered. Maybe this will get fixed by Typed Objects if they ever land in ES.
GWT's needs are primarily two fold: 1) recognize Java types that can be promoted to struct-types. GWT already knows how to do this as it has passes to convert all methods of a class to monomorphic/static dispatch, meaning the prototype only has to contain field values. Thus if a Java type has no polymorphic methods, and all fields are either primitives, or references to other 'struct' types, then the compiler can emit typed objects.
2) Since Java is a GC'ed language, GWT currently isn't in the business of implementing a memory management scheme. We rely on Javascript to do this. The current problem with strict asmjs output is we'd need to allocate typed arrays and our own memory management scheme. There's not much appetite for that right now, but I suppose it could change in the future.
Overall GWT is a decent performer, but not near the top. It is however nice that GWT can beat standard JS by a small amount.
It might be possible to locate a few hot methods and instrument just those with asmjs assertions and see if it has any effect. I don't know how Firefox reacts to something that's "half-way" asmjs (asserts types on math expressions, but still uses objects with fields instead of typedarrays), but FTLJIT and Turbofan are claiming they'll make use of them even in the non-strict case. We'll see.
Right now I'm spending most of the my time implementing Java8 lambdas, Promises, and all that good stuff that removes the "tax" of java boilerplate so I don't have much time to explore it, but given how early Turbofan seems to be, waiting might be good anyway.
1) already attached to Java language and toolchain 2) code sharing with Server, Android, etc (see Google Inbox) 3) Optimized compiles (Closure can also do the same for JS)
Modern JIT JS engines do remove the need for most performance optimizations, but GWT and Closure Compiler have never really biased towards runtime performance, they have almost exclusively focused on code size.
GWT does do some optimizations that help with performance, but most web apps are not bottlenecked by raw Javascript performance. However for mobile apps in particular, especially those on slow networks all over the world, shipping smaller code will matter for latency, startup time, memory usage, etc.
Subjective perception of speed in web browsers is very often a function of DOM complexity, and excessive style recalc, layout, paint. You could reduce the JS execution to zero and still end up with an app that feels laggy as hell.
I don't recommend people switch to GWT unless they have a reason to use Java. You can implement a lot of these optimizations on whatever language you like.
My philosophy is to use whatever you feel most comfortable in. I'm kind of tired of 2 decades of language wars in the tech community. I work on GWT because I used it for my own startup several years ago and needed to make patches to the project to improve it, and now I just like working on the compiler because it is an interesting problem space.
Personally, if I was writing non-Web apps, Rust looks to me like an exciting language. I'm more on the side of "more typing" as opposed to less (Go), and for non-Web apps, I like to work on games, and there, I want absolute best performance. Outside of C/C++, Rust looks to be the best new game in town (ok, I've heard good things about D). Swift, I don't trust as being too proprietary and wedded to Objective-C semantics.
Now, I wonder who's going to write a Rust-to-JS compiler? :)
Isn't that a bit cheaty? IE is potentially a lot faster with that change, which Haxe's port benefits from. Haxe's port got more work put into, so proclaiming it a winner because Emscripten was already pretty fast without any work put into the port makes me doubtful of the results.
(Also, Haxe's UInt 0xFFFFFFFF not being converted to -1 sounds like a bug waiting to happen.)
Haxe, on the other hand, is a high-level language that could be compiled to JavaScript much more simply.
But then, I'm not sure why Dart would be slow, then, given it's also quite high-level. Tree-shaking of the standard library? Having to compile the standard library?
Being a high-level language, and using the same compiler infrastructure, it would have to be transpiled into a fairly low-level IR for the consumption of the various backends before being spit out as JS again.
I think the fact that its high level makes it much LESS simple.
It definitely isn't just mapping Haxe constructs to JS. It is much too feature rich.