Understanding JavaScript Heaps

In a futile attempt to write perfect javascript, I deal with the Javascript heap issue. I lowered it to the lowest level I can, but I have run out of options, and I don’t understand what’s going on (well, I think this is rAF overhead, but guesses are not taken into account).

Pile of sawtooth (light blue):

enter image description here

The above chart is taken from a simple visualization of the canvas particles on the entire page. The goal of this exercise is to reduce the amplitude of the sawtooth heap and possibly also increase the period between cleanings.

If you look closely, the heap increases by about 15 KB every 60 seconds and drops from 3.3 MB to 2.4 MB every ~ 1 second.

enter image description here

What I don’t understand is the timing and amount of growth of 15K.

The heap increases by 15 KB immediately before downtime and ~ 0.015 ms after the next function returns to idle (below is my top-level function).

var renderList = []; var stop = false; var i; function update(timer) { // Main update loop if(!stop){ requestAnimationFrame(update); } for(i = 0; i < renderList.length; i ++){ renderList[i](timer,ctx, w, h); } } 

Nothing I do with the code reduces or changes the location of the heap growth. The distribution profile shows that I do not allocate any memory. GC is at 0.08% in the processor profile (what does it do, I don’t know ?, does it also manage the heap?)

Can someone explain to me what this memory is used for? and how can I reduce or make the line flat?

I understand that I can not do anything, but at the moment I have no vague idea of ​​what is put in a heap? It would be nice to know.

A snippet is just the code called from update (the code snippet above). I do not think it is appropriate, but just in case. This is the code that was executed and returned immediately before the heap growth.

  var p,d,s; var renderCount = 0; var fxId = 0; var lastTime; var frameTime = 0; var minParticles = 10; var particleCount = minParticles; var frameSum = 0; var frameAve = 0; var frameWorkTime = 0; var lastFrameWorkTime = 0; var particleRenderTimeMax = 0; var m = 0; var mC = 0; var mR = 0; var then,tx,ty; var renderTime,then1; //===================================================================================== // the following function is out of context and just placed here as reference /* draw : function (image, index, x, y, scale, rotation, alpha) { spr = image.sprites[index]; ctx.setTransform(scale, 0, 0, scale, x, y); ctx.rotate(rotation); ctx.globalAlpha = alpha; sh = spr.h; sw = spr.w; if(spr.vx !== undefined){ // virtual sprite dimensions _x = -spr.vw / 2 + spr.vx; _y = -spr.vh / 2 + spr.vy; ctx.drawImage(image, spr.x, spr.y, sw, sh, _x, _y, sw, sh); return; } ctx.drawImage(image, spr.x, spr.y, sw, sh, -sw / 2, -sh / 2, sw, sh); }, */ //===================================================================================== // Add particle function addP(x,y,spr){ p = particles.fNextFree(); if(particles.fLength >= particleCount || p === undefined){ // no room for more return; } px = x; py = y; p.spr = spr; p.life = 100; ps = Math.random() +0.1 d = Math.random() * Math.PI * 2; s = Math.random() * Math.PI * 2; p.dx = Math.cos(d) * s; p.dy = Math.sin(d) * s; p.dr = Math.random()-0.5; p.maxLife = p.life = 100-spr*10; } // move and draw particle function updateDrawP(p,i){ if(i >= particleCount){ p.life = undefined; return; } s = p.life/p.maxLife; px += p.dx * s; py += p.dy * s; pr += p.dr; p.life -= 1; if(p.life === 0){ p.life = undefined; return; } renderCount += 1; sDraw(spriteSheet, p.spr, px, py, ps, pr, s); // Calls draw (function example above) } function renderAll(time) { // this is called from a requestAnimationFrame controlled function var then = performance.now(); // get frame start time var tx, ty; if (lastTime !== undefined) { frameTime = time - lastTime; frameSum *= 0.5; frameSum += frameTime; frameAve = frameSum * 0.5; // a running mean render time } lastTime = time; ctx.setTransform(1, 0, 0, 1, 0, 0); // reset transform ctx.globalAlpha = 1; // reset alpha ctx.clearRect(0, 0, w, h); if (spriteSheet.sprites) { mouseWorld = EZSprites.world.screen2World(mouse.x, mouse.y, mouseWorld); if (mouse.buttonRaw & 1) { fxId += 1; fxId %= EZSprites.FX.namedFX.length; mouse.buttonRaw = 0; } if (mouse.buttonRaw & 4) { world.posX += mouse.x - mouse.lastX; world.posY += mouse.y - mouse.lastY; EZSprites.world.setPosition(world.posX, world.posY); mouseWorld = EZSprites.world.screen2World(mouse.x, mouse.y, mouseWorld); } if (mouse.w !== 0) { if (mouse.w > 0) { EZSprites.world.zoom2Screen(mouse.x, mouse.y, ZOOM_AMOUNT, true); mouse.w -= ZOOM_WHEEL_STEPS; } else { EZSprites.world.zoom2Screen(mouse.x, mouse.y, ZOOM_AMOUNT, false); mouse.w += ZOOM_WHEEL_STEPS } mouseWorld = EZSprites.world.screen2World(mouse.x, mouse.y, mouseWorld); EZSprites.world.getWorld(currentWorld); world.posX = currentWorld.x; world.posY = currentWorld.y; } // sets the current composite operation (only using source-over) EZSprites.FX[EZSprites.FX.namedFX[fxId]](); // render and time particles renderCount = 0; var then1 = performance.now(); particles.fEach(updateDrawP); // render all particles var renderTime = performance.now() - then1; EZSprites.context.setDefaults(); // gets the total time spent inside this function frameWorkTime += performance.now() - then; lastFrameWorkTime = frameWorkTime; if (renderCount > 0) { particleRenderTimeMax = Math.max(particleRenderTimeMax, renderTime / renderCount); particleRenderTimeMax *= 10; particleRenderTimeMax += renderTime / renderCount particleRenderTimeMax /= 11; // Smooth out per particle render time max m = particleRenderTimeMax; mC += (m - mR) * 0.1; mC *= 0.1; mR += mC; // Particle count is being balanced to keep ensure there is plenty of idle time before // the next frame. Mean time spent in this function is about 8 to 9ms particleCount = Math.floor(((1000 / 120) - (frameWorkTime - renderTime)) / (mR)); } // This is where frameWorkTime begins its timing of the function then = performance.now(); frameWorkTime = 0; if (particleCount <= maxParticles) { particles.fMaxLength = particleCount; } // Add particles. addP(mouse.x, mouse.y, 1); addP(mouse.x, mouse.y, 2); addP(mouse.x, mouse.y, 3); addP(mouse.x, mouse.y, 4); addP(mouse.x, mouse.y, 5); addP(mouse.x, mouse.y, 1); addP(mouse.x, mouse.y, 2); addP(mouse.x, mouse.y, 3); addP(mouse.x, mouse.y, 4); addP(mouse.x, mouse.y, 5); } mouse.lastX = mouse.x; mouse.lastY = mouse.y; frameWorkTime = performance.now() - then; } 
+5
source share

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


All Articles