使用 `new Function()` 优化 Javascript

标签 javascript optimization eval

在阅读文档时,我发现了一个可以大大提高 javascript 性能的简单优化。

原代码:

function parseRow(columns, parser) {
  var row = {};
  for (var i = 0; i < columns.length; i++) {
    row[columns[i].name] = parser.readColumnValue();
  }
}

优化代码:

var code = 'return {\n';
columns.forEach(function(column) {
  code += '"' + column.name + '":' + 'parser.readColumnValue(),\n';
});
code += '};\n';

var parseRow = new Function('columns', 'parser', code);

在这里找到:https://github.com/felixge/faster-than-c
为什么它的运行速度提高了 20%?
我相信它删除了 for 语句,但是 forEach 是否具有相同的计算成本?

最佳答案

区别在于您只使用了 forEach 构建优化函数。创建函数后,内部没有任何循环:loop is unrolled和列名是 hardcoded .然后方法是eval编辑成一个工作函数,甚至可以编译成机器代码,depending on the engine .这会带来两项性能改进:

  1. 删除 for完全循环条件检查(i < columns.length),没有分支,
  2. 通过对 column[i].name 的值进行硬编码在多个语句中,您删除了评估 column[i]并查找 column.name在每一步。

所以在调用new Function(...)之后代码作为 String 传递, 你的 parseRow变量获取对以下函数的引用:

function parseRow(columns, parser) {
    return {
        "columnOne": parser.readColumnValue(),
        "columnTwo": parser.readColumnValue(),
        "columnThree": parser.readColumnValue(),
        ...
    };
}

请注意,除了多个 parser.readColumnValue() 之外,该代码中没有任何循环、分支或其他查找。电话。

为什么这在 JavaScript 中可行?

这在 JavaScript 中如此有效的原因是因为任何网页中的 JavaScript 源代码无论如何都需要由 JS 引擎解释或编译。您不会在网页上发布已编译的可执行文件,甚至(某种程度上)预编译的字节码(如 Java 或 .NET)。每次都是新的 .js文件加载后,您的浏览器会在运行之前从头开始编译它(好吧,准确地说,在现代引擎中,它介于解释和编译之间,即 JITting )。

这意味着在运行时从字符串创建工作函数(即编译代码)的效率不亚于从 .js 文件中读取手写代码。将其与 C/C++ 程序进行比较,C/C++ 程序(在所有合理的情况下)被编译为机器代码(即尽可能接近 CPU 的可执行文件)before it reaches the customer .

如果您想在 C++ 中执行此操作(类似于 self-modifying code),则必须在您的应用程序中捆绑一个编译器来构建代码,构建此函数的成本会超过您将获得的 yield 当你最终开始它时。例如,在 .NET 中,程序 emit methods or even assemblies at run time 也很常见。 ,然后将 JIT 编译为机器代码,从而实现潜在的性能改进,例如您问题中的那个。

关于使用 `new Function()` 优化 Javascript,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/25823024/

相关文章:

javascript - toLocaleDateString() 如何在 Chrome 中工作?

javascript - 如何优化这个 javascript 重复项

python - 测试在循环内不会改变的条件

php - 使用评估();直接从数据库执行php

javascript - 我在哪里可以找到像 facebook 这样的滚动条插件?

javascript - XMLHttpRequest JS 图片加载

javascript - 将图像源设置为本地文件

r - 在 constrOptim 中与简单的约束作斗争

javascript - JavaScript 的 eval() 什么时候不邪恶?

javascript - 为什么 {} + {} 仅在客户端是 NaN?为什么不在 Node.js 中?