Javascript optimization with the `new Function ()` function

When reading documents, I found a simple optimization that greatly improves javascript performance.

Source:

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

Optimized Code:

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

Found here: https://github.com/felixge/faster-than-c
Why does it work 20% faster?
I believe it removes the for statement, but does forEach have the same computational cost?

+5
source share
2 answers

The difference is that you only use forEach to construct an optimized function. After creating a function, there is no loop inside the loop: the loop is expanded , and the column names are hard . Then, the eval ed method turns into a working function, which can even be compiled into machine code , depending on the engine . This leads to two performance improvements:

  • i < columns.length completely removing the for loop state check ( i < columns.length ), there is no branching, and
  • Based on the hard-coded values ​​of column[i].name in several statements, you removed the rating of column[i] and searches on column.name at every step.

So, after calling new Function(...) with the code passed as a String , your parseRow variable gets a reference to the following function:

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

Note that in this code there are no loops, branches, or other requests, except for a few calls to parser.readColumnValue() .

Why is this possible in JavaScript?

The reason this works so effectively in JavaScript is because the JavaScript source code on any web page needs to be interpreted or compiled by the JS engine anyway. You do not send your web page with compiled executables or even (several) precompiled bytecode (e.g. Java or .NET). Each time a new .js file is uploaded, your browser will compile it from scratch before launching it (well, more precisely, in modern machines this is something between interpretation and compilation, i.e. JITting ).

This means that creating a working function from a string (for example, compiling code) at run time is no less efficient than reading handwritten code from a .js file. Compare this with a C / C ++ program that (in all reasonable cases) is compiled into machine code (i.e. an executable file that is as close to the CPU as possible) before it reaches the client .

If you want to do this in C ++ (a kind of self-modifying code ), you will have to associate the compiler with your application to create the code, and the cost of creating this function will be overweight for the benefits that you will get when you can start it. For example, in .NET it is also unusual for a program to emit methods or even assemblies at runtime that then receive JITs compiled for machine code, which can improve performance, for example, in your question.

+5
source

The performance gain depends on the JavaScript engine, as well as the data being processed. We do not know the exact circumstances "20% faster" (except for using node.js). In some situations, this may be slower. ( Edit: You will need to call the function often enough to outweigh the construction cost). Some possible reasons for winning:

Optimized code creates an object literal. The previous version constantly assigns values ​​to properties that do not yet exist. This is associated with some costs.

row[columns[i].name] has three searches, while the optimized version does not, as soon as the function is built. And don't forget that row[columns[i].name] doesn't exist yet, so the search is more expensive. columns.length is also a search.

+2
source

Source: https://habr.com/ru/post/1202489/


All Articles