I've got a web page that's using jquery to receive some product information as people are looking at things and then displays the last product images that were seen. This is in a jquery AJAX callback that looks pretty much like this:
if(number_of_things_seen > 10) {
$('#shots li:last-child').remove();
}
$('<li><img src="' + p.ProductImageSmall + '"></li>').prependTo('#shots');
However, it seems to leak quite a bit of memory. Visually, it does the right thing, but the footprint grows indefinitely.
Safari's DOM inspector shows the DOM is how I would expect it to be, but it seems to maintain references to every image that it has displayed (as seen in this screenshot in case anyone is interested).
I've added
$('#shots li:last-child img').remove();
to the removal statement to no noticable effect.
Is there some magic necessary to let the browser release some of this stuff?
Use reference objects to avoid memory leaks ref package, you can work with the garbage collector in your program. This allows you to avoid directly referencing objects and use special reference objects that the garbage collector easily clears. The special subclasses allow you to refer to objects indirectly.
The JavaScript engine allocates memory when you create objects and variables in your application, and it is smart enough to clear out the memory when you no longer need the objects. Memory leaks are caused due to flaws in your logic, and they make way for poor performance in your application.
Start with metrics such as page load times, HTTP request times, and Core Web Vitals – time to the first byte, first contentful paint. If you use Sematext Experience you'll see a number of other useful metrics for your web applications and websites there. However, metrics themselves are only a part of the whole picture.
Browsers are notorious for memory leaks. It sounds like the problem occurs when the page is left running for a long time. How about refreshing the page before it runs out of memory?
window.setTimeout("location.reload()",1000*60*60);//refresh in an hour
Can you try changing the src of the last-child and see if that makes a difference? You can then move that element to be the first child
//not tested
var $list=$('#shots>li');
$list.filter(':last-child').children('img')
.attr('src', p.ProductImageSmall)
.parent()
.insertBefore( $list.eq(0) );
From the Mozilla Developer Center on removeChild()
:
The removed child node still exists in memory, but is no longer part of the DOM. You may reuse the removed node later in your code, via the oldChild object reference.
This is the key - reuse the removed child, instead of repeatedly making a new one.
// I'm sure there is a nicer way to do it in jQuery
if(number_of_things_seen > 10) {
var shots = document.getElementById("shots");
var li = shots.getElementsByTagName("LI");
var move = shots.removeChild(li[li.length-1]);
move.getElementsByTagName("IMG")[0].src = p.ProductImageSmall;
shots.insertBefore(move, li[0]);
}
Is the footprint really a problem?
I suspect that Safari caches all images as long as you stay on the same site and there's nothing you can do about it. If you're lucky Safari releases not-needed objects after some limit is reached.
The reason for this behaviour is, that Safari thinks it's likely that those images are used a second time, and therefore it caches them.
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With