J@ArangoDB

{ "subject" : "ArangoDB", "tags": [ "multi-model", "nosql", "database" ] }

ES6 Features in ArangoDB 2.7

ArangoDB 2.6 uses V8 engine version 3.31.74.1 for running its own and all user-defined JavaScript code. In ArangoDB 2.7 (currently in development), we have upgraded V8 to version 4.3.61.

The new V8 version in ArangoDB 2.7 provides several additional ES6 features that can be used to improve JavaScript usability and code quality. This blog post showcases strong mode and rest parameters, and also shows how to activate TurboFan, V8’s new JIT compiler for JavaScript.

ArangoDB 2.7 is in development right now, but it can be tried today by compiling it from source.

JavaScript strong mode

V8 v4 comes with an optional and experimental strong mode. This mode provides only a subset of JavaScript, with the idea of intentionally deactivating some of JavaScript’s bad parts. It is based on strict mode, but goes further.

Committing to strong mode may not only provide better and stronger semantics, but may also enable more optimization opportunities for the JavaScript compiler. For example, the strong mode disables JavaScript’s with statement and delete! Additionally, var cannot be used anymore but is deprecated in favor of let and const.

The proposal for the strong mode can be found here, and the V8 team also has a page about it.

Strong mode must be turned on explicitly. This can be done by adding the --strong-mode=true v8 option when starting arangod or arangosh:

enabling strong mode
1
arangosh  --javascript.v8-options="--strong_mode=true"

Note that I am using arangosh above, but the same would work for arangod, too, so the feature can be used for Foxx routes as well.

Rest parameters

How to pass a variable number of arguments to a function?

C and C++ programmers have been using and abusing the ellipsis (...) and __VA_ARGS__ features of the C preprocessor for a long time. Then came the macros of stdarg.h / cstdarg, until C++11 really improved the situation with std::initializer_list and variadic templates.

In JavaScript, one can use the arguments object:

1
2
3
4
5
6
7
function logSimple () {
  for (value of arguments) {
    console.log(value);
  }
}

logSimple("foo", "bar", "baz");

This does the job, and the above will print something like:

1
2
3
2015-07-14T19:01:51Z [5245] INFO foo
2015-07-14T19:01:51Z [5245] INFO bar
2015-07-14T19:01:51Z [5245] INFO baz

This is fine as long as all arguments shall be treated the same way. But what if some arguments have a designated meaning and should be treated specially?

The solution is to use ES6 rest parameters. The last parameter in an argument list can be prefixed with ... to capture any number of function parameters:

1
2
3
4
5
6
7
function logWithContext (context, ...values) {
  for (value of values) {
    console.log('[' + context + '] ' + value);
  }
}

logWithContext("es6", "foo", "bar", "baz");

As can be seen, the logWithContext function specially handles its context argument, while we can still pass any number of further parameters into it. Here’s what the above will print:

1
2
3
2015-07-14T19:07:27Z [5245] INFO [es6]: foo
2015-07-14T19:07:27Z [5245] INFO [es6]: bar
2015-07-14T19:07:27Z [5245] INFO [es6]: baz

Note that rest parameters cannot be used with the default configuration and must be turned on explicitly in arangosh or arangod.

The startup option to turn them on is:

enabling rest parameters
1
arangosh --javascript.v8-options="--harmony_rest_parameters=true"

TurboFan

The new V8 version comes with TurboFan, a new JIT compiler for JavaScript. According to this post it is already used in Chrome for compiling certain types of JavaScript code.

As fas as I can see, it is turned off by default in our version of V8, and the compiler also seems to be rather experimental. To get an idea of what it can already do and where its limits are, it can already be tried in ArangoDB 2.7.

By default, it seems to be turned off. Using the following startup option, it can be turned on for JavaScript functions with a certain name pattern (i.e. all function names starting with testTurboFan):

starting ArangoShell with TurboFan enabled
1
arangosh --javascript.v8-options="--turbo-filter=testTurboFan*"`

Without turning on V8 tracing, one will not be able to tell which compiler is used to compile a specific function. To turn it on and actually confirm V8 is using TurboFan, use these options:

starting ArangoShell with TurboFan and debug output
1
arangosh --javascript.v8-options="--always-opt --trace_opt --turbo-filter=testTurboFan*"

This will be very verbose, but it is good to tell which internal compiler is used to compile a given JavaScript function.

For example, after starting the ArangoShell with the above options, run the following test code to see that V8 uses TurboFan for compiling the first two functions (which match the name pattern), and Crankshaft for the third (which does not match the name pattern):

test code for invoking the TurboFan compiler
1
2
3
4
5
6
7
8
9
10
11
12
13
14
function testTurboFan1 () {
  console.log("turbo-fan 1");
}
testTurboFan1();

function testTurboFan2 () {
  console.log("turbo-fan 2");
}
testTurboFan2();

function testSomethingElse () {
  console.log("something else");
}
testSomethingElse();

Here’s the confirmation that TurboFan is used:

debug output
1
2
3
4
5
6
7
...
[compiling method 0x31ca8804e351 <JS Function testTurboFan1 (SharedFunctionInfo 0x31ca8804e171)> using TurboFan]
...
[compiling method 0x31ca8804e7f9 <JS Function testTurboFan2 (SharedFunctionInfo 0x31ca8804e619)> using TurboFan]
...
[compiling method 0x31ca8804ec71 <JS Function testSomethingElse (SharedFunctionInfo 0x31ca8804ea91)> using Crankshaft]
...

Have fun!