9

我正在编写一个恒定时间字符串比较函数(用于 node.js),并希望为这个单一函数禁用 V8 的优化编译器;使用命令行标志是不可能的。

我知道现在使用with{}或 try/catch)块会禁用优化编译器,但恐怕这个“功能”(错误)将在未来的版本中得到修复。

是否有禁用 V8 优化编译器的不可变(和记录)方式?


示例函数:

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;
    }
}

还有一个性能测试只是为了好玩。

4

2 回答 2

13

如果你想要可靠的方法来做到这一点,你需要运行带有--allow-natives-syntax标志的节点并调用它:

%NeverOptimizeFunction(constantTimeStringCompare);

请注意,您应该在调用之前调用它constantTimeStringCompare,如果函数已经优化,那么这违反了断言。

否则with声明是您最好的选择,因为使其可优化将是绝对的疯狂,而支持try/catch将是合理的。不过,您不需要它来影响您的代码,这就足够了:

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;

}

仅仅提及with语句会破坏整个包含函数 - 优化是在函数级别的粒度上完成的,而不是每个语句。

于 2013-08-28T12:46:18.340 回答
4

要实际检查特定 Node.js 版本是否对功能进行了优化,您可以参考Bluebird 的Optimization Killers wiki。
我在 Node 7.2 上检查了 3 个解决方案:

  1. with({})- TurboFan优化功能
  2. try {} catch(e) {}- TurboFan优化功能
  3. eval('');- 功能未优化

所以为了保证禁用 V8 优化,你应该添加eval('')到函数体中。

于 2017-07-24T12:45:51.880 回答