Realtime JavaScript
100 - 200 milliseconds, that’s the time a bot has each tick to do its stuff. Included are path finding, building placement, unit management, combat planning, village layout and resource planning + allocation.
It is a relief to not write JavaScript against 5 or more browsers on mobile, tablet or desktop. With 0 A.D. there is only one engine and the current version already implements many ES6 features like fat arrows, sets, maps and more. However finding the sweet spot and have SpiderMonkey generating fast code is not exactly intuitive. Here is an example showing different ways of calling a function with multiple parameters:
// Call
o.f.call(o, d, e, f) // 15,702,342 ops/sec
// Call with null
o.f.call(null, d, e, f) // 15,399,460
// Direct
o.f(d, e, f) // 15,062,388
// Apply predefined array
o.f.apply(o, z) // 4,197,047
// Apply
o.f.apply(o, [d, e, f]) // 3,401,670
// Direct with Spread
o.f(...z) // 924,084
// Direct with Spread II
o.f(...[d, e, f]) // 660,252
// Call with spread
o.f.call(o, ...z) // 627,680
All timings refer to a 3GHZ Intel Duo Core running FF30 on Windows XP. Try for yourself at jsperf.com. Some calls are factor 25 faster, and it is a shame call and apply are in different ballparks considering this MDN note:
While the syntax of this function is almost identical to that of call(), the fundamental difference is that call() accepts an argument list, while apply() accepts a single array of arguments.
Here is the winner:
// New Function
o.ff(d, e, f) // 15,902,228
The first examples look like this:
f = function (a, b, c) {return [a, b, c];}
Why is ff() faster? It is not embedded in a closure.
ff = new Function('a', 'b', 'c', 'return [a, b, c];')
Well, you know people say eval is evil and new Function() is no different, but this kind of extreme lambda lifting seems to have some convincing advantages.
Expect more non-idiomatic JavaScript soon…