1

I am creating a single page application that will remain active and open for multiple days at a time in a browser. On this page I am displaying a timer in the top right corner. I have found however, that the way I am using the timer is leaking a small amount of memory.

https://jsfiddle.net/zbgonp84/

$(function(){
    timer();
});
function timer(){
    var today = new Date();
    var h = today.getHours();
    var m = today.getMinutes();
    var s = today.getSeconds();
    m = checkTime(m);
    s = checkTime(s);
    $("#timer").text(h + ":" + m + ":" + s);
    var t = setTimeout(timer, 1000);
}

function checkTime(i) {
    if (i < 10){
        i = "0" + i;
    }
    return i;
}

I have recreated just the timer and the timer's div in a fiddle. If you open chrome's dev tools and record a time line, you can see that every second a new node is added to memory. If left for 24 hours, it will add a new node every second for the whole day and never gets collected.

I feel as if I am missing something fairly obvious as to why this is not being garbage collected, but what am I missing to unallocate the memory?

Jermaya
  • 156
  • 10
  • Are you referring to `timer` reference and use of `setTimeout`? What is expected result? You are also calling `jQuery()` at each call to `timer`. – guest271314 Dec 05 '16 at 20:34
  • How does `garbage collector` is connected? What garbage it should collect? – u_mulder Dec 05 '16 at 20:35
  • have you tried calling `.empty()` before changing `.text()` – Steve0 Dec 05 '16 at 20:37
  • I am expecting the node count to increase by 1, and then continue to use the same reference. However it seems to be creating a new reference to #timer every time the function runs. Commenting out the $("#timer").text() line prevents any new nodes from being created. @u_mulder I expect it to collect the old $("#timer") reference. – Jermaya Dec 05 '16 at 20:38
  • @Steve I just tried adding .empty before .text, however the nodes continue to increase. How would i reference the timer every call without calling jQuery() on each call? – Jermaya Dec 05 '16 at 20:40
  • Isn't this just a case of the dev tools showing the increase of nodes since it collects the stack traces of the `setTimeout` callback? There's no actual memory leak, it's just how the timeline recording works and how it's reflected in the tool. – Daniel B Dec 05 '16 at 20:41
  • http://javascript.crockford.com/memory/leak.html – Jaber Dec 05 '16 at 20:43
  • @Daniel B It seems you may be right. Although calling .empty() on the element before keeps the js heap down. So a combination of the two seem to have resolved my minor issue. Thanks for the help, seems my issue lies elsewhere in my code. – Jermaya Dec 05 '16 at 20:49
  • Cool! Found a similar issue, almost certain the same applies here! [Does JavaScript setInterval() method cause memory leak?](http://stackoverflow.com/questions/14034107/does-javascript-setinterval-method-cause-memory-leak/14851513#14851513) – Daniel B Dec 05 '16 at 20:52
  • Good read, looks like i got caught up whether or not Jquery or my code was causing issues, and missed that it could have been chrome itself and how I was interpreting the timeline. Thanks again. – Jermaya Dec 05 '16 at 21:00

1 Answers1

1

Create and substitute a reference to #timer element for calling jQuery() at each call to timer. Also, declare variable t outside of timer

$(function() {
  const time = $("#timer");
  var t;
  timer();

  function timer() {
    var today = new Date();
    var h = today.getHours();
    var m = today.getMinutes();
    var s = today.getSeconds();
    m = checkTime(m);
    s = checkTime(s);
    time.text(h + ":" + m + ":" + s);
    t = setTimeout(timer, 1000);
  }

  function checkTime(i) {
    if (i < 10){
        i = "0" + i;
    }
    return i;
  }
});
guest271314
  • 1
  • 15
  • 104
  • 177