2

I have the following which is updating an element on the screen, and I can't seem to prevent it from consuming memory, it is consuming roughly 0.10% or ram every minute.

I have already tried to null all of the variables, but nothing I seem to do will stop this leak.

function TimeTick(){
    var lt = new Date(); 
    lt.setMilliseconds(lt.getMilliseconds()-g_svros);
    var ch=lt.getHours(), cm=lt.getMinutes(), cs=lt.getSeconds(); 
    if(ch==0) ch=12; 
    $('#clock').val((ch >12?ch-12:ch)+":"+(cm<10?"0":"")+cm+":"+(cs<10?"0":"")+cs+" "+(ch>=12?"PM":"AM"));
    lt=null;ch=null;cm=null;cs=null;
}
var tick = setInterval('TimeTick()',250);

I profiled the memory usage of the browser from the command prompt by sampling the browser process.

If I disable this function, then the memory does not increas and stays perfectly stable !

crankshaft
  • 2,607
  • 4
  • 45
  • 77

3 Answers3

0

'TimeTick()' is being eval`d every 250ms.

See if this makes a difference:

var tick = setInterval(function () {
    TimeTick();
}, 250);

See eval benchmarks here.

pdoherty926
  • 9,895
  • 4
  • 37
  • 68
0

Here's a fiddle that removes the eval and function declaration, and moves the jquery selector outside the function: http://jsfiddle.net/aBvdy/1/

$(function() {
    var g_svros = 0;
    var clock = $('#clock');
    var tick = setInterval(function() {
        var lt = new Date(); 
        lt.setMilliseconds(lt.getMilliseconds()-g_svros);
        var ch=lt.getHours(), cm=lt.getMinutes(), cs=lt.getSeconds(); 
        if(ch==0) ch=12; 
        clock.val((ch >12?ch-12:ch)+":"+(cm<10?"0":"")+cm+":"+(cs<10?"0":"")+cs+" "+(ch>=12?"PM":"AM"));
    }, 250);
});

I watched the Chrome process manager for about 5 minutes, only very slight fluctuations in memory usage for that tab. Nothing to call home about.

000
  • 26,951
  • 10
  • 71
  • 101
  • deleted due to longer test – crankshaft Sep 06 '13 at 05:24
  • OK, have been testing this solution, an improvement over my original, now the memory is climbing at about 0.1% every 6 minutes, rather than every minute or so, but I would still like to get this to zero, as after many hours or days, eventually all of the memory will be used. – crankshaft Sep 06 '13 at 05:36
  • That is an issue with the browser and the OS. You can open `about:blank` and the same thing will happen. Browsers use memory in pages at a time, and the OS cleans it up every once in a while. It'll climb and it'll garbage-collect. You are trying to accomplish something beyond your control. Be happy with the 0.1%/6minute memory usage. – 000 Sep 06 '13 at 05:38
  • Thanks Joe, but if I disable this function, the memory usage does not appear to grow at all. The O/S is Arch Linux, the browser is Midori (webkit) – crankshaft Sep 06 '13 at 07:55
0

Let's do some optimizations (when I say each time I mean each iteration of the TimeTick function):

  1. Stop creating new date object each time since it is fairly costly (it's useful if you want to block up the browser!) Nevermind, you need to do this to get the new Date each time.
  2. Don't reselect #clock element each time, jQuery has to access the DOM each time
  3. Use anonymous function instead of eval since eval entails much more overhead (parsing, etc.)
  4. Remove the nulling of variables, what did these achieve? Since JS has function scope, ch, cs, and cs are destroyed at the end of each TimeTock and then garbage collected.

Modified Code:

function TimeTick(lt, clock) {
     lt.setMilliseconds(lt.getMilliseconds()-g_svros);
     var ch= lt.getHours(), cm=lt.getMinutes(), cs=lt.getSeconds(); 
     if(ch==0) ch=12; 
     clock.val((ch >12?ch-12:ch)+":"+(cm<10?"0":"")+cm+":"+(cs<10?"0":"")+cs+" "+(ch>=12?"PM":"AM"));
}

var clock = $('#clock'); //Optimization 2
var tick = setInterval(function() {
    TimeTick(new Date(), clock); //Optimization 3
}, 250);
Community
  • 1
  • 1
sushain97
  • 2,752
  • 1
  • 25
  • 36