【问题标题】:Is the Function() constructor not optimized by V8, like eval?Function() 构造函数是否没有像 eval 那样被 V8 优化?
【发布时间】:2017-11-04 02:14:12
【问题描述】:

我们正在尝试一种通过 WebSockets 接收 Web 组件的方法。这些组件包含自定义脚本,它们应该在组件内部的上下文中运行。

简而言之,我们有一些脚本字符串并且想要运行它们。

现在我们为此使用eval,如下所示:

function ctxEval(ctx, __script) {
    eval(__script);
    // return things with the ctx
}

并按预期工作,但我读到任何包含 eval 的函数都没有被 V8 优化。我想像这样将其转换为new Function()

new Function("ctx", __script)(ctx);

这样我就可以实现和上面ctxEval函数一样的效果了。

我们知道Functioneval(),因为它们的作用几乎相同,但现在的问题是,直到Functioneval()?可能是因为Function() 有自己的作用域,而不是eval 在同一作用域内运行代码,所以包含Function 调用的函数实际上是由V8 优化的。另外,here 他们谈论的是eval,但不是Function 构造函数。

这其中隐含的另一个问题是,Function() 内部运行的脚本是否经过 V8 优化?

【问题讨论】:

  • 为什么首先需要使用eval?不能正常运行 JavaScript 吗?
  • 我想这就是你要找的答案chromium.googlesource.com/v8/v8.git/+/roll/src/…
  • @Halcyon 我们从套接字接收脚本作为字符串。不包含在连接服务器的主脚本中。
  • @ponury-kostek 所以匿名函数没有优化?不知道
  • @JorgeFuentesGonzález 只需将其设置为创建的脚本元素的innerHTML 并将其附加到文档中。不需要eval

标签: javascript optimization v8


【解决方案1】:

我刚刚用这段代码测试了这个

const adder = new Function('a', 'b', 'return b%2 ? a + b : b%3 ? a - b : b%5 ? b / a : a * b');
let b = 0, b2 = 0;
function _throw() {
    throw new Error('Ups');
}
function _catch() {
    try {_throw()} catch(e) {}
}
function printStatus(fn) {
    switch (%GetOptimizationStatus(fn)) {
        case 1: console.log(fn.name, "function is optimized"); break;
        case 2: console.log(fn.name, "function is not optimized"); break;
        case 3: console.log(fn.name, "function is always optimized"); break;
        case 4: console.log(fn.name, "function is never optimized"); break;
        case 6: console.log(fn.name, "function is maybe deoptimized"); break;
    }
}
eval('function evil(a,b) {return b%2 ? a + b : b%3 ? a - b : b%5 ? b / a : a * b}');
printStatus(adder);
printStatus(evil);
printStatus(_throw);
printStatus(_catch);
// Call the function
for(let i = 0; i < 2000; i++) {
    b = adder(Math.random() * 10, b);
    b2 = evil(i, b2);
    _catch();
}
printStatus(adder);
printStatus(evil);
printStatus(_throw);
printStatus(_catch);

运行命令

$ node --allow-natives-syntax js.js

输出是

anonymous function is not optimized
evil function is not optimized
_throw function is not optimized
_catch function is not optimized

anonymous function is optimized
evil function is optimized
_throw function is not optimized
_catch function is not optimized

编辑:

我修改了这个测试代码来检查其他 bailots,我真的很惊讶,因为它看起来 eval 也被优化了:>

编辑 2:

经过一些额外的研究,我发现了这个https://blog.sqreen.io/optimize-your-node-app-by-simply-upgrading-node-js/

【讨论】:

  • 还不错。所以运行后进行了优化。需要测试包含new Function调用的父函数。
  • @JorgeFuentesGonzález 在一些额外的测试后检查新的有趣结果
  • 是的,也在做一些测试。我有一个有点过时的节点,似乎 evalFunction 的优化不同,所以我认为是的,尽管它们评估字符串,但在优化它们时它们的工作方式不同:gist.github.com/Llorx/975779da3919d3777877ca5b748e1a15
  • @JorgeFuentesGonzález 我已经在节点 v8.2.1(稍后使用 v8.7.0)上运行了你的代码(以及 ponury-kostek 的代码),我得到了一些优化代码范围(如 17 和 49)查看 v8 源代码时没有描述此类状态代码(而是 2:1、2、4、8 到 2024 的乘法)。有任何想法吗? v8 OptimizationStatus
  • @yuval.bl 哦,我看到你已经回复了。他们是正确的。它们是位掩码。
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2012-05-07
  • 2016-08-12
  • 2016-07-12
  • 1970-01-01
  • 2011-04-19
相关资源
最近更新 更多