Home  >  Article  >  Web Front-end  >  Summarize the five major JavaScript optimization principles

Summarize the five major JavaScript optimization principles

零到壹度
零到壹度Original
2018-04-02 17:01:341119browse

First of all, unlike other languages, the efficiency of JS largely depends on the efficiency of the JS engine. In addition to the pros and cons of engine implementation, the engine itself will also adopt some optimization strategies for some special code patterns. For example, the JS engines of FF, Opera and Safari have specially optimized the string concatenation operation (+). Obviously, to achieve maximum efficiency, you must understand the temperament of the engine and try to cater to the engine's taste. Therefore, for different engines, the optimizations made are most likely to run counter to each other.

And if you do cross-browser web programming, the biggest problem is IE6 (JScript 5.6)! Because without hotfix, the garbage collection bug of the JScript engine will cause its performance in real applications to not be on the same order of magnitude as other browsers. Therefore, optimizing in this situation is actually optimizing for JScript!

So the first principle is to only optimize for IE6 (unpatched JScript 5.6 or earlier)!

If your program has been optimized to acceptable performance under IE6, then basically there will be no problem with performance on other browsers.

Therefore, please note that many of the issues I talk about below may be completely different on other engines. For example, when string splicing is performed in a loop, it is usually considered that Array.join is required, but due to Engines such as SpiderMonkey have optimized the "+" operation on strings. As a result, using Array.join is not as efficient as using "+" directly! But if you consider IE6, this efficiency difference on other browsers is not worth mentioning at all.

JS optimization still has similarities with optimization in other languages. For example, don’t rush into optimization as soon as you start, as that is meaningless. The key to optimization is still to focus on the most critical place, which is the bottleneck. Generally speaking, bottlenecks always appear in large-scale loops. This is not to say that loops themselves have performance issues, but that loops can quickly amplify possible performance issues.

So the second principle is to take large-scale loops as the main optimization object.

The following optimization principles are only meaningful in large-scale loops. It is basically meaningless to do such optimization outside the loop body.

Currently, most JS engines are interpreted and executed. In the case of interpreted execution, the efficiency of function calls is low in all operations. In addition, excessively deep prototype inheritance chains or multi-level references will also reduce efficiency. In JScript, the overhead of level 10 references is roughly 1/2 of the overhead of an empty function call. The overhead of both is much greater than simple operations (such as four arithmetic operations).

So the third principle is to try to avoid too many reference levels and unnecessary multiple method calls.

Special attention should be paid to the fact that in some cases, what appears to be property access is actually a method call. For example, all DOM attributes are actually methods. When traversing a NodeList, the loop condition's access to nodes.length looks like attribute reading, but is actually equivalent to a function call. Moreover, in the implementation of IE DOM, childNodes.length must be re-counted through internal traversal each time. (My god, but this is true! Because I have measured that the access time of childNodes.length is proportional to the value of childNodes.length!) This is very expensive. Therefore, saving nodes.length to a js variable in advance can certainly improve the performance of traversal.

It’s also a function call, and the efficiency of user-defined functions is far lower than that of language built-in functions, because the latter is a wrapper for the engine’s native methods, and the engine is usually c, Written in c++, java. Furthermore, for the same function, the cost of built-in language constructs is usually more efficient than built-in function calls, because the former can be determined and optimized during the parse stage of JS code.

So the fourth principle is to try to use the constructs and built-in functions of the language itself.

Here is an example of High-performance String.format method. The traditional implementation of String.format is to use String.replace(regex, func). When pattern contains n placeholders (including repeated ones), the custom function func is called n times. In this high-performance implementation, each format call only performs an Array.join and then a String.replace(regex, string) operation. Both are built-in methods of the engine without any custom function calls. Two built-in method calls and n number of custom method calls, this is the difference in performance.

are also built-in features, but there are still differences in performance. For example, the access performance of arguments in JScript is very poor, almost catching up with a function call. Therefore, if a simple function with variable parameters becomes a performance bottleneck, you can make some internal changes and do not access the arguments, but handle it through explicit judgment of the parameters.

For example:

Java code Summarize the five major JavaScript optimization principles

  1. function sum() {  
        var r = 0;  
        for (var i = 0; i < arguments.length; i++) {  
            r += arguments[i];  
        }  
        return r;  
    }


This sum is usually called with a small number of parameters. We hope to improve its performance when there are fewer parameters. If changed to:


##Java code Summarize the five major JavaScript optimization principles

    function sum() {  
        switch (arguments.length) {  
            case 1: return arguments[0];  
            case 2: return arguments[0] + arguments[1];  
            case 3: return arguments[0] + arguments[1] + arguments[2];  
            case 4: return arguments[0] + arguments[1] + arguments[2] + arguments[3];  
            default:  
                var r = 0;  
                for (var i = 0; i < arguments.length; i++) {  
                    r += arguments[i];  
                }  
                return r;  
        }  
    }


In fact, there will not be much improvement, but if it is changed to:


Java代码  Summarize the five major JavaScript optimization principles

  1. function sum(a, b, c, d, e, f, g) {  
        var r = a ? b ? c ? d ? e ? f ? a + b + c + d + e + f : a + b + c + d + e : a + b + c + d : a + b + c : a + b : a : 0;  
        if (g === undefined) return r;  
        for (var i = 6; i < arguments.length; i++) {  
            r += arguments[i];  
        }  
        return r;  
    }


就会提高很多(至少快1倍)。 

最后是第五原则,也往往是真实应用中最重要的性能障碍,那就是尽量减少不必要的对象创建。 

本身创建对象是有一定的代价的,但是这个代价其实并不大。最根本的问题是由于JScript愚蠢之极的垃圾回收调度算法,导致随着对象个数的增加,性能严重下降(据微软的人自己说复杂度是O(n^2))。 

比如我们常见的字符串拼接问题,经过我的测试验证,单纯的多次创建字符串对象其实根本不是性能差的原因。要命的是在对象创建期间的无谓的垃圾回收的开销。而Array.join的方式,不会创建中间字符串对象,因此就减少了那该死的垃圾回收的开销。 

因此,如果我们能把大规模对象创建转化为单一语句,则其性能会得到极大的提高!例如通过构造代码然后eval——实际上PIES项目中正在根据这个想法来做一个专门的大规模对象产生器…… 

好了上面就是总结的JS优化五大原则。 

The above is the detailed content of Summarize the five major JavaScript optimization principles. For more information, please follow other related articles on the PHP Chinese website!

Statement:
The content of this article is voluntarily contributed by netizens, and the copyright belongs to the original author. This site does not assume corresponding legal responsibility. If you find any content suspected of plagiarism or infringement, please contact admin@php.cn