最新消息:雨落星辰是一个专注网站SEO优化、网站SEO诊断、搜索引擎研究、网络营销推广、网站策划运营及站长类的自媒体原创博客

javascript - How to Disable V8's Optimizing Compiler - Stack Overflow

programmeradmin3浏览0评论

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.

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.

Share Improve this question edited Aug 27, 2013 at 22:39 David Murdoch asked Aug 27, 2013 at 22:17 David MurdochDavid Murdoch 89.3k39 gold badges152 silver badges192 bronze badges 24
  • 1 @DavidMurdoch That's called linear time, since the execution time as a function of the input length is a linear function. Also this function is probably worse than builtin string comparison - you're missing three very common shortcuts. – millimoose Commented Aug 28, 2013 at 12:55
  • 1 @DavidMurdoch Your first question is a very contrived scenario. Generally the "value" of the run-time function is how many times a given operation is executed given an input of size n. In your case, this operation would be the character comparison. Since this would be the length of the longer string, it doesn't matter that a is constant, since for all strings b longer than a the value of this function would be b.length. (Since there is an infinite amount of strings longer than a, and a finite number of strings shorter than a, we can ignore the shorter ones in our analysis.) – millimoose Commented Aug 28, 2013 at 17:00
  • 1 @DavidMurdoch Also, for algorithm complexity, you generally consider asymptotic complexity. The shortcut that checks for reference equality can be disregarded here. The other I can remember now is checking whether the lengths are equal, which is a constant-time check assuming string lengths are known beforehand. (As is the case in Javascript.) Meaning that a function that uses it would be constant-time for inputs of inequal length, and linear-time for inputs of equal length. So yes, in this case leaving out those checks would guarantee that your function is linear-time for all strings. – millimoose Commented Aug 28, 2013 at 17:08
  • 1 @DavidMurdoch Whereas with those shortcuts, it would be constant-time theoretically for most pairs of strings and linear for an infinitesimal subset of all pairs of strings. Practically, it would depend on your range of inputs. Even without them as you've noticed the function wouldn't be perfectly linear because of the overhead of .length and max() – millimoose Commented Aug 28, 2013 at 17:09
  • 1 @DavidMurdoch It is. It's also incorrect. Your function determines whether a is a prefix of b. (To make this a constant-time comparison, you'd in fact have to implement the "optimisations" I've mentioned.) Also counting all operations into counter makes no sense. You usually count the instances of one or sometimes several "representative" operations, separately. Reads or writes to input elements (in your case characters) are common, as are comparisons between input elements. You can safely ignore constant overhead. – millimoose Commented Aug 28, 2013 at 20:58
 |  Show 19 more comments

2 Answers 2

Reset to default 14

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:

  1. with({}) - Function is optimized by TurboFan
  2. try {} catch(e) {} - Function is optimized by TurboFan
  3. eval(''); - Function is not optimized

So to guarantee disable V8 optimization you should add eval('') to function body.

发布评论

评论列表(0)

  1. 暂无评论