I'm writing a constant-time string comparison function (for node.js) and would like to disable V8's optimizing compiler for this single function; using command-line flags are out of the question.
I know that using a with{}
(or try/catch) block will disable the optimizing compiler now, but I'm afraid this "feature" (bug) will be fixed in future versions.
Is there an immutable (and documented) way disabling V8's optimizing compiler?
Example function:
function constantTimeStringCompare( a, b ) {
// By adding a `with` block here, we disable v8's optimizing compiler.
// Using Object.create(null) ensures we don't have any object prototype properties getting in our way.our way.
with ( Object.create( null ) ){
var valid = true,
length = Math.max( a.length, b.length );
while ( length-- ) {
valid &= a.charCodeAt( length ) === b.charCodeAt( length );
}
// returns true if valid == 1, false if valid == 0
return !!valid;
}
}
And a perf test just for fun.
In computing, an optimizing compiler is a compiler that tries to minimize or maximize some attributes of an executable computer program. Common requirements are to minimize a program's execution time, memory footprint, storage size, and power consumption (the last three being popular for portable computers).
However, V8 does it incrementally, i.e., for each GC stop, V8 tries to mark as many objects as possible. It makes everything faster because there's no need to stop the entire execution until the collection finishes. In large applications, the performance improvement makes a lot of difference.
That's why it is so essential to implement objects with the same properties in the same order to have the same hidden class. Otherwise, V8 won't be able to optimize your code. In V8 words, you want to stay as much monomorphic as possible.
Unlike other languages, The V8 engine uses both a compiler and an interpreter and follows Just in Time(JIT) Compilation for improved performance. Just in Time(JIT) Compilation: The V8 engine initially uses an interpreter, to interpret the code.
If you want solid way to do it, you need to run node with --allow-natives-syntax
flag and call this:
%NeverOptimizeFunction(constantTimeStringCompare);
Note that you should call this before you have called constantTimeStringCompare
, if the function is already optimized then this violates an assertion.
Otherwise with
statement is your best bet as making it optimizable would be absolute lunacy whereas supporting try/catch
would be reasonable. You don't need it to affect your code though, this will be sufficient:
function constantTimeStringCompare( a, b ) {
with({});
var valid = true,
length = Math.max( a.length, b.length );
while ( length-- ) {
valid &= a.charCodeAt( length ) === b.charCodeAt( length );
}
// returns true if valid == 1, false if valid == 0
return !!valid;
}
Merely mentioning with
statement corrupts the entire containing function - the optimizations are done at function-level granularity, not per statement.
To actually check is function optimized by particular Node.js version you can refer to Optimization Killers wiki of bluebird.
I've checked 3 solutions on Node 7.2:
with({})
- Function is optimized by TurboFantry {} catch(e) {}
- Function is optimized by TurboFaneval('');
- Function is not optimizedSo to guarantee disable V8 optimization you should add eval('')
to function body.
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With