Write a failed jquery optimization attempt

Source: Internet
Author: User
Tags object commit functions key new features return access advantage

I often complain that jquery's Dom does not perform well and often tries to optimize it in a number of ways, but the more optimized it is, the more frustrated it is to discover that jquery is actually doing well and that the optimizations that can be done from the user's perspective are limited (this does not mean that jquery is a good performance Conversely, it can only be said that it is a relatively closed library, can not be optimized from outside intervention. This article records a failed optimization experience.

Optimization ideas

This time the idea of optimization comes from the database. In database optimization, we often say that a large number of operations in a transaction together to submit, can effectively improve efficiency. Although I do not know the reasons for the database, but the idea of the business for me to indicate the direction (although it is wrong).

So I tried to introduce the concept of a transaction into jquery, to optimize the jquery from the outside by opening and submitting transactions, and the most important thing was to reduce the number of loops in each function.

As we all know, jquery's DOM operations, with get all, set first as the standard, where the DOM attributes/styles are manipulated, is almost always a traversal of the selected elements, The Jquery.access function is the most important part of the loop, and the code for looping is as follows:

 
  
  
  1. Setting one attribute
  2. if (value!== undefined) {
  3. Optionally, function values get executed if exec are true
  4. exec =!pass exec jquery.isfunction (value);
  5. for (var i = 0; I length; i++) {
  6. fn
  7. Elems[i],
  8. Key
  9. Exec? Value.call (Elems[i], I, FN (Elems[i], key)): value,
  10. Pass
  11. );
  12. }
  13. return elems;

For example, the JQUERY.FN.CSS function is like this:

 
  
  
  1. jquery.fn.css = function ( name, value )  {  
  2.     // Setting  ' undefined '  is a no-op  
  3. Li class= "alt" >    if  ( arguments.length === 2  value == = undefined )  { 
  4.         return this;  
  5.     }  
  6.  
  7. return  Jquery.access ( this, name, value, true, function ( elem, name, value  )  { 
  8. return value !== undefined ?  
  9. jquery.css ( elem, name  );  
  10. }; 

So the following code, assuming there are 5,000 div elements selected, iterates through 10,000 nodes:

 
  
  
  1. JQuery (' div '). css (' height ', #). css (' width ', 200);

In my mind, in a transaction, such as the operation of the database, through the preservation of all operations, in the submission of the transaction at the same time, the 10,000 node access, reduced to 5,000 times, the equivalent of a 1 time-fold increase in performance.

Simple implementation

In a transactional jquery operation, 2 functions are provided:

begin: Opens a transaction that returns the object of a transaction. The object has all the functions of jquery, but the calling function does not take effect immediately, only when the transaction is committed.

Commit: Commit a transaction to ensure that all previously called functions are in effect and return the original jquery object.

It is also convenient to implement:

creates a transaction object that replicates all functions on the Jquery.fn to that object.

When a function is called, the called function name and related parameters are added to the prepared queue.

When a transaction is committed, the selected element is traversed once, and all functions in the queue are applied to each node in the traversal.

The simple code is as follows:

 
 
  1. var slice = Array.prototype.slice;
  2. JQuery.fn.begin = function () {
  3. var proxy = {
  4. _CORE:C,
  5. _queue: []
  6. },
  7. Key
  8. Func
  9. To copy a function on a Jquery.fn
  10. For (key in Jquery.fn) {
  11. func = Jquery.fn[key];
  12. if (typeof func = = ' function ') {
  13. This will cause the key to always be the last loop value for the For loop.
  14. Therefore, a closure must be used to guarantee the validity of the key (lift effect)
  15. (function (key) {
  16. Proxy[key] = function () {
  17. To place a function call in a queue
  18. This._queue.push ([Key, Slice.call (arguments, 0)]);
  19. return this;
  20. };
  21. }) (key);
  22. }
  23. }
  24. Prevent the commit function from being intercepted
  25. Proxy.commit = JQuery.fn.commit;
  26. return proxy;
  27. };
  28. JQuery.fn.commit = function () {
  29. var core = This._core,
  30. queue = This._queue;
  31. Only one per loop
  32. Core.each (function () {
  33. var i = 0,
  34. Item
  35. JQ = JQuery (this);
  36. Call all functions
  37. for (; item = queue[i]; i++) {
  38. Jq[item[0]].apply (JQ, item[1]);
  39. }
  40. });
  41. return THIS.C;
  42. };

Test environment

The test uses the following criteria:

The 5,000 div is placed in a container (div id= "container"/div).

use $ (#containerdiv) to select these 5,000 div.

each div requires setting a random background color (Randomcolor function), and a random width below 800px (randomwidth function).

There are 3 calling methods to participate in the test:

Normal use method:

 
  
  
  1. $ (' #containerdiv ')
  2. . css (' Background-color ', Randomcolor)
  3. . css (' width ', randomwidth);

Single Cycle method:

 
  
  
  1. $ (' #containerdiv '). each (function () {
  2. $ (this). CSS (' Background-color ', Randomcolor). css (' width ', randomwidth);
  3. });

Business Law:

 
  
  
  1. $ (' #containerdiv ')
  2. . Begin ()
  3. . css (' Background-color ', Randomcolor)
  4. . css (' width ', randomwidth)
  5. . commit ();

Object Assignment method:

 
  
  
  1. $ (' #containerdiv '). CSS ({
  2. ' Background-color ': Randomcolor,
  3. ' Width ': randomwidth
  4. });

Test browser to choose the Chrome 8 series (with IE test directly hang).

The result of the sadness

The original prediction is that the efficiency of the single cycle is much higher than the normal use method, while the transaction method is slower than the single cycle method, but should be faster than the normal use of the method, and the object assignment method is in fact jquery internal support of the single cycle method, the efficiency should be the highest.

Unfortunately, however, the results are as follows:

Normal use method Single Cycle method Business Law Object Assignment method
18435ms 18233ms 18918ms 17748ms

As a result, the law of affairs has become the slowest method. At the same time, there is no obvious advantage of single cycle and normal use, even the object assignment method which relies on the internal implementation of jquery has not opened a big gap.

Since the operation of 5,000 elements is already a very large cycle, such a large cycle has not been able to pull off the gap in performance, usually the most commonly used 10 or so elements of the operation is more unlikely to have a clear advantage, or even may be enlarged disadvantage.

The reason is that there is no obvious performance improvement because of the single cycle method. Therefore, relying on a single cycle, and on a single loop on the external construction of the transaction method, is naturally on a single cycle on the basis of the additional need to create transaction objects, save function queues, traverse function queues and other costs, As a result, the normal use of the method is also understandable.

At this point, it is also a failure to declare the optimization of the business of imitation. But the results can be further analyzed.

Where is the performance?

First of all, from the use of code analysis, the normal use of the test and the fastest object assignment method to compare, can be said that the difference between the two is only the number of elements of the cycle (here, the internal problem of jquery is thrown away, In fact, the poor implementation of Jquery.access does have a drag-and-Drop object assignment method, fortunately not serious, the normal use of the method is 10,000 elements, the object assignment method is 5,000 elements. Therefore, it is easy to think that 18435 17748 = 687ms is a cycle of 5,000 elements of the time consuming, which accounted for the entire implementation of the process of 3.5% or so, not the backbone of the entire implementation process, in fact, there is really no need for optimization.

So where did the other 96.5% of the spending go? Remember Doglas's words, in fact, JavaScript is not slow, slow is the operation of the DOM. In fact, the remaining 96.5% of the cost, to remove the function call and other basic consumption, at least 95% of the time is used in the DOM elements of the style is changed after the rendering.

After discovering this fact, there is also a more correct direction of optimization, but also one of the basic principles of front-end performance: When you modify a large number of child elements, first move the root parent DOM node out of the DOM tree. So if you use the following code to test again:

 
  
  
  1. No reuse $ (' #container ') already bad.
  2. $ (' #container '). Detach (). Find (' div ')
  3. . css (' Background-color ', Randomcolor)
  4. . css (' width ', randomwidth);
  5. $ (' #container '). Appendto (Document.body);

Test results always stay at around 900ms, and the previous data is not at all an order of magnitude above, the real optimization success.

Lessons and summaries

Be sure to find the right performance bottlenecks and then optimize, blind speculation will only lead to the wrong and extreme road.

data to speak, no one to speak in front of the data!

do not think that the direction of the transaction is wrong, if jquery native can support the concept of transactions, there will be other points can be optimized? For example, a transaction automatically gets the parent element out of the DOM tree.

Original link: http://www.otakustay.com/a-failure-in-jquery-optimization/

"Edit Recommendation"

    1. JQuery 1.5 Official release five major changes compelling
    2. 18 new and most-given jquery tutorials to share
    3. Simplifying Ajax development with JQuery
    4. Dynamic adding and statistics of tabular data by jquery
    5. The redemption of the plug-in mechanism of jQuery1.5 new features
"Responsible editor: Chen Yu new TEL: (010) 68476606"


Contact Us

The content source of this page is from Internet, which doesn't represent Alibaba Cloud's opinion; products and services mentioned on that page don't have any relationship with Alibaba Cloud. If the content of the page makes you feel confusing, please write us an email, we will handle the problem within 5 days after receiving your email.

If you find any instances of plagiarism from the community, please send an email to: info-contact@alibabacloud.com and provide relevant evidence. A staff member will contact you within 5 working days.

A Free Trial That Lets You Build Big!

Start building with 50+ products and up to 12 months usage for Elastic Compute Service

  • Sales Support

    1 on 1 presale consultation

  • After-Sales Support

    24/7 Technical Support 6 Free Tickets per Quarter Faster Response

  • Alibaba Cloud offers highly flexible support services tailored to meet your exact needs.