ovi*_*ovi 5 javascript optimization eval
在阅读文档时,我发现了一个简单的优化,可以极大地提高javascript的性能.
原始代码:
function parseRow(columns, parser) {
var row = {};
for (var i = 0; i < columns.length; i++) {
row[columns[i].name] = parser.readColumnValue();
}
}
Run Code Online (Sandbox Code Playgroud)
优化代码:
var code = 'return {\n';
columns.forEach(function(column) {
code += '"' + column.name + '":' + 'parser.readColumnValue(),\n';
});
code += '};\n';
var parseRow = new Function('columns', 'parser', code);
Run Code Online (Sandbox Code Playgroud)
在这里找到:https ://github.com/felixge/faster-than-c
为什么它运行速度提高20%?
我相信它删除了for声明,但是没有forEach相同的计算成本?
不同之处在于您仅forEach用于构建优化函数.创建函数后,内部没有任何循环:循环展开,列名称是硬编码的.然后将该方法eval编入工作函数,甚至可以将其编译成机器代码,具体取决于引擎.这导致两项性能改进:
for循环条件check(i < columns.length),没有分支,和column[i].name到多个语句中,您在每个步骤中删除了评估column[i]和查找column.name.因此,在new Function(...)使用作为a传递的代码调用之后String,您的parseRow变量将获得对以下函数的引用:
function parseRow(columns, parser) {
return {
"columnOne": parser.readColumnValue(),
"columnTwo": parser.readColumnValue(),
"columnThree": parser.readColumnValue(),
...
};
}
Run Code Online (Sandbox Code Playgroud)
请注意,除了多个parser.readColumnValue()调用之外,该代码中没有任何循环,分支或其他查找.
为什么这在JavaScript中可行?
之所以在JavaScript中如此高效地运行,是因为任何网页中的JavaScript源代码都需要由JS引擎解释或编译.您不会使用已编译的可执行文件,甚至(某种程度上)预编译的字节码(如Java或.NET)发布您的网页.每次.js加载一个新文件时,你的浏览器都会在运行之前从头开始编译它(确切地说,在现代引擎中它是解释和编译之间的东西,即JITting).
这意味着在运行时从字符串创建工作函数(即编译代码)并不比从.js文件读取手写代码有效.将它与C/C++程序进行比较,C/C++程序(在所有合理的情况下)在到达客户之前编译为机器代码(即可以接近CPU的可执行文件).
如果你想用C++(一种自修改代码)来做这件事,你必须在应用程序中捆绑一个编译器来构建代码,而构建这个函数的成本会超过你获得的好处.终于会开始了.例如,在.NET中,程序在运行时发出方法甚至程序集也是不寻常的,然后将JIT编译为机器代码,从而允许潜在的性能改进,例如您的问题.