Network Security Internet Technology Development Database Servers Mobile Phone Android Software Apple Software Computer Software News IT Information

In addition to Weibo, there is also WeChat

Please pay attention

WeChat public account

Shulou

Example Analysis of jQuery Optimization failure

2025-01-18 Update From: SLTechnology News&Howtos shulou NAV: SLTechnology News&Howtos > Development >

Share

Shulou(Shulou.com)06/02 Report--

This article is to share with you the example analysis of jQuery optimization failure, the editor thinks it is very practical, so I share it with you to learn. I hope you can get something after reading this article.

I often complain that the DOM operation performance of jQuery is not good, and I often try to optimize it in some ways, but the more I optimize, the more frustrated I find that jQuery has actually done a good job, and what can be optimized from the user's point of view is really limited (this does not mean that jQuery's performance is excellent, on the contrary, it is a relatively closed library, can not be optimized from the outside). This article records a failed optimization experience.

Optimization thought

The idea of optimization this time comes from the database. When optimizing the database, we often say that committing a large number of operations together in a transaction can effectively improve efficiency. Although I don't know why I don't know anything about the database, the idea of transactions points me in the wrong direction.

So I try to introduce the concept of transaction into jQuery and optimize jQuery externally by opening and committing transactions, the most important of which is to reduce the number of loops of the each function.

As we all know, the DOM operation of jQuery is based on get all and set first. Almost all the operations used to set DOM attributes / styles are a traversal of the selected elements, and the jQuery.access function is the core part. The code for the loop is as follows:

/ / Setting one attribute if (value! = = undefined) {/ / Optionally, function values get executed if exec is true exec =! pass exec jQuery.isFunction (value); for (var I = 0; I length; iTunes +) {fn (elems [I], key, exec? Value.call (elems [I], I, fn (elems [I], key)): value, pass);} return elems

For example, the jQuery.fn.css function looks like this:

JQuery.fn.css = function (name, value) {/ / Setting 'undefined' is a no-op if (arguments.length = 2 value = = undefined) {return this;} return jQuery.access (this, name, value, true, function (elem, name, value) {return value! = undefined? JQuery.style (elem, name, value): jQuery.css (elem, name);};}

Therefore, the following code, assuming that 5000 div elements are selected, iterates through 10000 nodes:

JQuery ('div'). Css (' height', 300). Css ('width', 200)

In my opinion, in a transaction, like the operation of a database, all operations can be saved and carried out uniformly when the transaction is committed, reducing 10000 node visits to 5000, which is equivalent to a double improvement in performance.

Simple implementation

In transactional jQuery operations, two functions are provided:

◆ begin: opens a transaction and returns the object of a transaction. This object has all the functions of jQuery, but the calling function does not take effect immediately, only after the transaction is committed.

◆ commit: commits a transaction that ensures that all previously called functions take effect and returns the original jQuery object.

It's also easy to implement:

◆ creates a transaction object and copies all the functions on jQuery.fn into the object.

◆ when a function is called, the name of the called function and related parameters are added to the pre-prepared queue.

When ◆ commits a transaction, it iterates over the selected element and applies all the functions in the queue to each node in the traversal.

The simple code is as follows:

Var slice = Array.prototype.slice; jQuery.fn.begin = function () {var proxy = {_ core: C, _ queue: []}, key, func; / / copy the function for (key in jQuery.fn) {func = jQuery.fn [key] on jQuery.fn If (typeof func = = 'function') {/ / here the problem that key is always * a cyclic value is generated because of the for loop / / so a closure must be used to guarantee the validity of the key (LIFT effect) (function (key) {proxy [key] = function () { / / put the function call in the queue this._queue.push ([key Slice.call (arguments, 0)]) Return this;};}) (key);}} / / avoid that the commit function is also intercepted proxy.commit = jQuery.fn.commit; return proxy;}; jQuery.fn.commit = function () {var core = this._core, queue = this._queue / only one each loop core.each (function () {var I = 0, item, jq = jQuery (this); / / call all functions for (; item = queue [I]; iTunes +) {jq [item [0]] .apply (jq, item [1]);}}); return this.c;}

Test environment

The test uses the following conditions:

◆ has 5000 div in one container (div id= "container" / div).

◆ uses $(# containerdiv) to select the 5000 div.

Each div of ◆ requires a random background color (randomColor function) and a random width below 800px (randomWidth function).

There are three calling methods that participate in the test:

Normal use of ◆:

$('# containerdiv') .css ('background-color', randomColor) .css (' width', randomWidth)

◆ single cycle method:

$('# containerdiv') .each (function () {$(this) .css ('background-color', randomColor) .css (' width', randomWidth);})

◆ transaction method:

$('# containerdiv') .begin () .css ('background-color', randomColor) .css (' width', randomWidth) .commit ()

◆ object assignment method:

$('# containerdiv') .css ({'background-color': randomColor,' width': randomWidth})

The test browser chooses Chrome 8 series (just hang up with IE test).

The result of grief

The original prediction result is that the efficiency of the single cycle method is much higher than that of the normal use method, and although the transaction method is slower than the single cycle method, it should be faster than the normal use method, while the object assignment method is actually a single cycle method supported internally by jQuery, and its efficiency should be *.

Unfortunately, the results are as follows:

Normal use method single cycle method transaction method object assignment method 18435ms18233ms18918ms17748ms

As a result, the transaction method has become one of the slowest methods. At the same time, there is no obvious advantage between single loop and normal use, and even the object assignment method which relies on the internal implementation of jQuery does not open a big gap.

As the operation of 5000 elements is already a very large cycle, such a large cycle has not been able to open the performance gap, the most commonly used operation of about 10 elements is less likely to have obvious advantages, and may even enlarge the disadvantages.

The reason is that because there is no obvious performance improvement in the single loop method itself, it depends on the single loop and is a transaction method built externally on top of the single loop. Naturally, on the basis of a single loop, additional costs such as creating transaction objects, saving function queues, traversing function queues and so on are needed, so it is reasonable to lose to the normal use method.

At this point, it is also possible to declare the failure of the optimization of imitating transactions. However, this result can be further analyzed.

Where is the performance?

First of all, from the analysis of the use of the code, compare the normal usage method with the fastest object assignment method in the test, it can be said that the difference between the two only lies in the number of elements in the cycle (here put aside the internal problems of jQuery, in fact, the poor implementation of jQuery.access is also suspected of holding back the object assignment method, but fortunately it is not serious), the normal usage method is 10000 elements, and the object assignment method is 5000 elements. Therefore, we can simply think that 18435 17748 = 687ms is the time-consuming cycle of 5000 elements, which accounts for about 3.5% of the entire execution process, and is not the backbone of the entire execution process. In fact, there is really no need for optimization.

So where did the other 96.5% go? Remember a sentence from Doglas, in fact, Javascript is not slow, it is the operation of DOM that is slow. In fact, of the remaining 96.5% of the overhead, excluding basic consumption such as function calls, at least 95% of the time is spent on re-rendering after the style of the DOM element has been changed.

After discovering this fact, there is actually a more correct direction of optimization, which is also one of the basic principles in front-end performance: when modifying a large number of child elements, move the root parent DOM node out of the DOM tree first. So if you test again with the following code:

/ / it's too bad not to reuse $('# container'). Detach (). Find ('div') .css (' background-color', randomColor) .css ('width', randomWidth); $(' # container') .appendto (document.body)

The test results always stay around 900ms, which is not the same order of magnitude as the previous data, and the real optimization is successful.

Lessons and summary

◆ must find the correct performance bottleneck before optimizing, blind guessing will only lead to the wrong and extreme path.

Talk about ◆ data, don't talk to anyone in front of the data!

◆ doesn't think that transactions are going in the wrong direction. If jQuery natively supports the concept of transactions, will there be other points that can be optimized? For example, a transaction will automatically detach the parent element from the DOM tree or something.

The above is the example analysis of jQuery optimization failure. The editor believes that there are some knowledge points that we may see or use in our daily work. I hope you can learn more from this article. For more details, please follow the industry information channel.

Welcome to subscribe "Shulou Technology Information " to get latest news, interesting things and hot topics in the IT industry, and controls the hottest and latest Internet news, technology news and IT industry trends.

Views: 0

*The comments in the above article only represent the author's personal views and do not represent the views and positions of this website. If you have more insights, please feel free to contribute and share.

Share To

Development

Wechat

© 2024 shulou.com SLNews company. All rights reserved.

12
Report