JS nakuplja rame?

Pozdrav, radio sam igricu u canvasu i zanima me koji su mogući razlozi da ta igrica počne blesirati (štekati) nakon nekog vremena rada.
Promatram rame…i oni lagano cijelo vrijeme rastu, dok je moj procesor na nekih 30% ak vrtim na mozilli.
Uglavnom…radi sve glatko nakon pokretanja…ali nakon nekog vremena počme lagano štekati. …ponekad se čak desi čak ( ali nakon izvjesnog vremena) da se procesor zakuca u vrh a igrica totalno uspori.

Gdje može biti problem? …, i za početak koji su razlozi skupljanja rama? Može li se to izbjeći??

vjerojatno je memory leak , koji nastaje kod nezdravih aplikacija…

1 Like

Aham…malo sam guglao o memory leak, i moglo bi biti to, hvala.

Ja sam podrazumjevao da sve lokalne varijable koje izgradim unutar različitih funkcija…da same i nestanu, no to očito ne mora biti slučaj.
Sad sam promjenio pristup, pa ćemo vidjeti rezultate…uglavnom, novi pristup je ovakav:
Više nikad unutar neke funkcije ne definiram lokalnu varijablu tipa:

function addDeset(x)
{
var rezultat=x+10;
return rezultat;
}

A novi pristup je:

function addDeset(x)
{
this.rezultat=x+10;
return this.rezultat;
//naravno moglo je ići odmah return x+10 , ali cisto za primjer
}

…računam da će se na ovaj način nova vrijednost rezultata uvijek prepisivati preko vrijednosti kod zadnjeg poziva funkcije. Ima li to smisla?

Lokalne varijable unutar funkcije su automatski “garbage collect-ane”.

Procitaj ovaj clanak, meni je pomogao: http://coding.smashingmagazine.com/2012/11/05/writing-fast-memory-efficient-javascript/

Velik članak, a ja moram jako brzo ovo rješiti :/. Mislim, proletio sam i prvom prilikom ću proučiti detaljnije …al ovako nisam uočio da radim neku kardinalnu grešku.

Ja bih u prvu ruku htio izolirati problem!! Znači, posumnjao sam u lokalne varijable koje kreiram unutar funkcija. Prema ovom članku one se automatski brišu …no isto tako ovaj novi pristup koji sam naveo, koliko vidim, nebi trebao nakupljati memoriju…nego bi prepisivao preko starih vrijednosti?

Znači tu problem nebi trebao biti, ali gdje onda je…grrrrrr.
Ja ću staviti sažeti kod, da se vidi tijek informacije…pa ako netko uoči gdje bi mogao biti problem, puno će mi pomoći!!!

Ovdje se vidi glavna petlja, koja poziva za svaki frame update funkciju svakog objekta (gdje se izvršava logika, računaju nove koordinate ovisno o brzini itd), i render funkciju svakog objekta (gdje se izvršava funkcija crtanja objekta)

var Game={}; 
Game.loop = function() 
    {
    objectUpdate({fps:Game.fps,shapes:Game.shapes});
    renderEkran({canvas:Canvas,shapes:Game.shapes});
    };
Game.fps=46;
function startGame(f)
    {
    Game.shapes=f.shapes
    Game.timeInterval = setInterval(function(){Game.loop()},1000/Game.fps);
    }  

E sad, funkcija objectUpdate prolazi kroz svaki objekt koji se nalazi u listi Game.shapes, i poziva funkciju update toga objekta ako ona postoji:

function objectUpdate(f)
    {
    this.t=1/f.fps;
    for(var x in f.shapes)
        {
        if(f.shapes[x].update)f.shapes[x].update(this.t);
        }
    }  

Funkcija render je zamišljena isto kao gornja update, ali s malim dodatkom. Prije nego protrči kroz listu Game.shapes, sortira tu listu prema vrijednosti y koordinate:

function renderEkran(f)
    {
    clearCanvas(f.canvas);
    var indexedList=sortObjectList(f.shapes,'y');
    for(var x in indexedList)if(indexedList[x].render)indexedList[x].render(f.canvas);
    }  

To je ono što se ponavlja puno puta …a u nastavku ću staviti ugrubo kako stvaram te objekte koji se nalaze u Game.shapes:

function newGame()
{
var igrac={};
igrac.img=new Image();
igrac.src='img/igrac.png';
igrac.x=0;
igrac.y=0;
igrac.z=0;
igrac.speed=10;

var lopta={};
lopta.img=new Image();
lopta.src='img/lopta.png';
lopta.x=10;
lopta.y=10;
lopta.z=10;
lopta.speed=100;

lopta.render=function(canvas)
  {
  canvas.drawImage(this.img,this.x,this.y,20,20);
  }
lopta.update=function(t)
  {
  lopta.x+=lopta.speed*t;
  if(lopta.x>200)igrac.speed=0;  // << znaci unutar jedne update funkcije, slobodno baratam drugim objektima koji su definirani unutar funkcije newGame()
 
  }

Mousetrap.bind('b',function(e) 
  {
  igrac.speed+=200;
  lopta.speed=0;
  //ovo je funkcija koja se aktivira pritskom na tipku "b", tu također slobodno baratam svim objektima koje sam definirao unutar funkcije newGame() 
  })

startGame({shapes:[igrac,lopta]});  // ovdje se znači aktivira timeInterval pokazan pri vrhu posta
}  

Hmm jedina optimizacija koja mi ovdje pada na pamet je to da umjesto ovoga:

var igrac={};
igrac.img=new Image();
igrac.src='img/igrac.png';
igrac.x=0;
igrac.y=0;
igrac.z=0;
igrac.speed=10;

radis ovako:

var igrac = {
    img  : new Image(),
    src  : 'img/igrac.png',
    x    : 0,
    y    : 0,
    z    : 0,
    speed: 10
};

Na taj naci JS engine moze bolje optimizirati taj objekt jer pri njegovoj kreaciji zna koje atribute objekt ima i kojeg su tipa. Isto bi trebao raditi na svim objektima gdje mozes.

No sumnjam da ce to sprijeciti memory leak koji ti se dogadja.

Jel moguće da je problem u nekoj sasvim drugoj domeni??
Ako se meni negdje nakuplja memorija zbog ne oslobađanja varijabli, to bi značilo da nakon refresha stranice sve mora raditi glatko kao na početku?? Ali to nije tako!

Kad radim neko duže vrijeme…i kad refresham stranicu, situacija mi se popravi, ali puno kraće onda radi sve glatko. Kao da se browser umorio i da je zapamtio da mu se neda tu igricu vrtiti…

Pokušao sam pratiti procese u task manageru, i tamo ima više linija vezanih uz chrome, a podaci miruju. Kad upalim igricu, vrijednosti u jednoj od tih linija počnu “plesati”. Znači podatak o memoriji baš “pleše” ali pritom i lagano raste…i tako kroz neko vrijeme ode sa 25.000K na 33.000K. (A tako dugo se vrtilo oko 25.000-27.000-25.000, da jedno vrijeme uopće nije odavalo tedenciju rasta!)

Nakon što je naraslo na 33.000, refresham stranicu…a ta memorija se ne promjeni :S ??


Copyright © 2022 WM Forum - AboutContact