The timeline of JS performance optimization

Source: Internet
Author: User
Tags acos cos setinterval

Tag: Rand Oat min operation clears www. Ima length Tin

Sometimes, we will automatically write some inefficient code, seriously affect the efficiency of the page run. Or we take over the project, the previous code written by many strange, such as for a Canvas special effects need to draw 600 a triangle at the same time, such as Coding.net's task center needs to watch tens of thousands of variable changes and so on. So, if we come across a more inefficient page, how do we optimize it?

Preparation before optimization: knowing the enemy

Before we start, let's Open the F12 panel and familiarize ourselves with the tools we'll use Next: Timeline:

Yes, that's it. Let me introduce you here. Area 1 is a thumbnail, you can see in addition to the time axis is divided into four blocks, respectively, representing FPS, CPU time, network communication time, stack occupancy; this thumbnail can be scaled horizontally, and the white area is the time period (gray of course not visible) that can be seen below. Area 2 You can see some interactive events, such as you scroll the page, then there will be a scroll line segment, the range of coverage is the time of scrolling. Zone 3 is a specific list of events.

When there is no record at first, all the areas are empty. Start statistics and end statistics are very simple, the upper left corner of the black Circle is. The button on the right that looks like a "no pass" is used to clear existing records. When there is data, we roll up the mouse wheel and we can see that the area is enlarged:

In a short time, the browser has done so many things. For the general screen, in principle, a second to draw frames on the screen 60 , so in theory we can not calculate time in a frame more than 16 milliseconds, but the browser in addition to execute our code, but also to do something else (such as the calculation of CSS, playing audio ...) ), so we can actually use only 10~12 about a millisecond.

Almost familiar with the operation, then come to the actual combat it! If one day, you took over a piece of code like this:

<!--a little animation: after clicking the button there will be an exploded particle effect--<! DOCTYPE html><Html><Head><Metacharset="Utf-8" ><Title>test</Title><Style> . Main{Position:Relative Width: 500px; Height: 500px; Background: #000; Overflow:Hidden } . Circle{Position:Absolute Border-radius: 50%; Border: 1px solid#FFF; Width: 8px; Height: 8px; } </Style></Head><Body><Divclass="Main" ></Div><Hr><buttononclick="ShowAnimation ()" > Point Me</Button><script src=  "jquery.min.js" ></script>  <script src= "animation.js" > </script> </body></ HTML>            
Animation.jsTotal number of particlesvar COUNT =500;Gravityvar G =-0.1;Frictionvar F =-0.04;function Init() {for (var i =0; i < COUNT; i++) {var d = math.random () *2 * MATH.PI;var v = math.random () *5;var circle = $ (' <div id= ' circle-' + i +' "class=" Circle "data-x=" "data-y=" + "data-d=" ' + D +' "data-v=" ' + V +' ></div> '); Circle.appendto ($ ('. Main '); }}function Updatecircle() {for (var i =0; i < COUNT; i++) {var x = parsefloat ($ (' #circle-' + i). attr (' Data-x '));var y = parsefloat ($ (' #circle-' + i). attr (' Data-y '));var d = parsefloat ($ (' #circle-' + i). attr (' data-d '));var v = parsefloat ($ (' #circle-' + i). attr (' Data-v '));var vx = v * Math.Cos (d);var vy = v * Math.sin (d);if (Math.Abs (VX) <1E-9) VX =0;Speed component Change VX + = F * Math.Cos (d); VY + = F * Math.sin (d) + G;Calculate new Speed v = MATH.SQRT (VX * vx + VY * vy);if (Vy >0) d = math.acos (vx/v);else D =-math.acos (vx/v);Displacement component Change x + = VX; Y + = VY; $(' #circle-' + i). attr (' Data-x ', x); $(' #circle-' + i). attr (' Data-y ', y); $( ' #circle-' + i). attr ( ' data-d ', d); $ ( #circle-' + i). attr ( ' data-v ', v); $ ( ' #circle-' + i). css ({400-y,  ' Left ': x}); }}var interval = null; function  showanimation () {if ( Interval) clearinterval (interval); $ (1000/60);           

The effect is as follows (the FPS counter in the upper-right corner comes with the Chrome debugging tool):

Only 10FPS ... 10FPS .. ...... Where's The pit daddy?

OK, open the Timeline, press the Record button, click on the page "point Me", a little later stop recording, you will get some data. Zoom in a bit, as you can see from the more familiar of jquery, these are mostly jquery functions. Let updateCircle 's click on that block and look at the following:

This tells us how long this function has been running and where the function code is. We click on the link and jump to the Source page:

is not very shocking, this page was just used for debugging, did not expect to now actually brought accurate to the line of running time statistics. This time, of course, is the time that this line is running in the "Execution time period for the chunks we clicked on just now". So let's take the slowest few words to do it!

Optimize one: Reduce DOM operations

Seeing these lines of code, the first reaction is: Mdzz. The DOM operation was slow, and the string and between the strings float . Be decisive! Then a separate array is used to store,,, and x y d v these properties.

var objects = [];// 在 init 函数中objects.push({    x: 250,    y: 250,    d: d,    v: v});// 在 updateCircle 函数中var x = objects[i].x;var y = objects[i].y;var d = objects[i].d;var v = objects[i].v;// ….objects[i].x = x;objects[i].y = y;objects[i].d = d;objects[i].v = v;

The effect is remarkable! Let's look at the exact data for the row:

Optimization Two: Reduce unnecessary operations

So the most time-consuming sentence has become a computational   VX   and   vy , after all, the trigonometric algorithm is more complex, understandable. As for why the trigonometric function behind is so fast, I guess the Chrome V8 engine will cache it (this is not guaranteed to be correct). However, I do not know if you have found, in fact, calculate   d   absolutely not necessary! We only need to save   VX   and   vy   No need to save   v   and   D !

// initvar vx = v * Math.cos(d);var vy = v * Math.sin(d);objects.push({    x: 250,    y: 250, vx: vx, vy: vy});// updateCirclevar vx = objects[i].vx;var vy = objects[i].vy;// 计算新速度var v = Math.sqrt(vx * vx + vy * vy);if (Math.abs(vx) < 1e-9) vx = 0;// 速度分量改变vx += F * vx / v;vy += F * vy / v + G;// ….objects[i].vx = vx;objects[i].vy = vy;

Only subtraction and open-squared operations, each time less than the original two milliseconds. From a fluent point of view, you can actually run a full frame, but why do I still feel a little bit of a card occasionally?

Optimization Three: Replace SetInterval

Since the occasional drop frame, then see how it was dropped. In principle, before each browser is drawn, there should be an event called paint in Timeline, like this:

Did you see these green things? That's them! Look at the timeline above, although setInterval the length of the code is 1000/16 milliseconds, but in fact there is no guarantee! So we need requestAnimationFrame to use it instead. This is the browser's own function specifically for animation services, the browser will automatically optimize the function of the call time. And if the page is hidden, the browser will also automatically pause the call, effectively reducing the CPU overhead.

// 在 updateCircle 最后加一句requestAnimationFrame(updateCircle);// 去掉全部跟 setInterval 有关的句子,把 showAnimation 最后一句直接改成这个updateCircle();

We can at least guarantee that each time we count, the screen will be displayed once, so the frame will not drop (provided that the time per calculation is less than 12ms ). But although the calculation time is low, the browser recalculates the style, the time to draw the image has not changed a bit. Can we do the optimization again?

Optimization Four: Use hardware acceleration, avoid repeatedly finding elements

If we use transform instead left and top to locate the element, then the browser will create a separate composite layer for this element, dedicated to rendering using the GPU, so that the cost of recalculation can be minimized. Interested students can look at the "CSS hardware acceleration" mechanism. At the same time, we can cache the elements of jQuery (or DOM elements) so that we do not have to re-search each time, but also a little bit more efficient. If you cache the elements in objects an array, you don't even have to id write them!

// initvar circle = $(‘<div class="circle"></div>‘);objects.push({ x: 250, y: 250, vx: vx, vy: vy, // 其实可以只存 DOM,不存 jQuery 对象 circle: circle[0]});// updateCircle 里面 for 循环的最后一句话替换掉objects[i].circle.style.transform = ‘translate(‘ + x + ‘px, ‘ + (400 - y) + ‘px)‘;

Does it look like it's cool?

In fact, the optimization is endless, for example, I init can not use jQuery in the function, instead of createDocumentFragment splicing elements, so that the initialization time can be sharply shortened, the order of several statements in the exchange, the efficiency of the updateCircle V8 engine may be a certain increase, or even can be combined Profile panel to analyze memory footprint, view browser drawing details ... However, personal feelings are not optimized to such a limit. For a project, it is very uneconomical to write some strange code simply for optimization.

Reprinted from: Https://blog.coding.net/blog/Chome-Timeline

The timeline of JS performance optimization

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.