How do I create a memory leak in JavaScript?

前端 未结 6 1659
南笙
南笙 2021-01-31 03:34

I would like to understand what kind of code causes memory leaks in JavaScript and created the script below. However, when I run the script in Safari 6.0.4 on OS X the memory co

6条回答
  •  轻奢々
    轻奢々 (楼主)
    2021-01-31 04:11

    update: Here is a very simple example based on the caching scenario in the Google I/O presentation:

    /*
    This is an example of a memory leak. A new property is added to the cache
    object 10 times/second. The value of performance.memory.usedJSHeapSize
    steadily increases.
    
    Since the value of cache[key] is easy to recalculate, we might want to free
    that memory if it becomes low. However, there is no way to do that...
    
    Another method to manually clear the cache could be added, but manually
    adding memory checks adds a lot of extra code and overhead. It would be
    nice if we could clear the cache automatically only when memory became low.
    
    Thus the solution presented at Google I/O!
    */
    
    (function(w){
        var cache = {}
        function getCachedThing(key) {
            if(!(key in cache)) {
                cache[key] = key;
            }
            return cache[key];
        }
    
        var i = 0;
        setInterval(function() {
            getCachedThing(i++);
        }, 100);
        w.getCachedThing = getCachedThing
    })(window);
    

    Because usedJSHeapSize does not update when the page is opened from the local file system, you might not see the increasing memory usage. In that case, I have hosted this code for you here: https://memory-leak.surge.sh/example-for-waterfr


    This Google I/O'19 presentation gives examples of real-world memory leaks as well as strategies for avoiding them:

    • Method getImageCached() returns a reference to an object, also caching a local reference. Even if this reference goes out of the method consumer's scope, the referenced memory cannot be garbage collected because there is a still a strong reference inside the implementation of getImageCached(). Ideally, the cached reference would be eligible for garbage collection if memory got too low. (Not exactly a memory leak, but a situation where there is memory that could be freed at the cost of running the expensive operations again).
    • Leak #1: the reference to the cached image. Solved by using weak references inside getImageCached().
    • Leak #2: the string keys inside the cache (Map object). Solved by using the new FinalizationGroup API.

    Please see the linked video for JS code with line-by-line explanations.

    More generally, "real" JS memory leaks are caused by unwanted references (to objects that will never be used again). They are usually bugs in the JS code. This article explains four common ways memory leaks are introduced in JS:

    1. Accidental global variables
    2. Forgotten timers/callbacks
    3. Out of DOM references
    4. Closures

    An interesting kind of JavaScript memory leak documents how closures caused a memory leak in the popular MeteorJS framework.

提交回复
热议问题