惯性聚合 高效追踪和阅读你感兴趣的博客、新闻、科技资讯
阅读原文 在惯性聚合中打开

推荐订阅源

H
Help Net Security
G
Google Developers Blog
aimingoo的专栏
aimingoo的专栏
博客园 - 聂微东
酷 壳 – CoolShell
酷 壳 – CoolShell
小众软件
小众软件
Stack Overflow Blog
Stack Overflow Blog
美团技术团队
博客园_首页
T
Tailwind CSS Blog
博客园 - 三生石上(FineUI控件)
B
Blog
D
DataBreaches.Net
腾讯CDC
C
Check Point Blog
钛媒体:引领未来商业与生活新知
钛媒体:引领未来商业与生活新知
U
Unit 42
月光博客
月光博客
V
V2EX
Vercel News
Vercel News
T
The Blog of Author Tim Ferriss
The Cloudflare Blog
博客园 - 叶小钗
Y
Y Combinator Blog

Steve Hanov's Blog

How this Canadian Startup Bought Millions of Impressions for $8,000 How to Run a Fellowship Program Into the Ground (and get 18M impressions in the process) My Waterloo Intern went back to school. I'll miss him dearly but here's how I replaced him with Hermes I learned Mandarin. Here's what it taught me about B2C SaaS. The VC's Waterloo Coffee Tour: Where to Find Canada's Next Unicorn How I run multiple $10K MRR companies on a $20/month tech stack How to Save a Gemini Canvas as Markdown A Ralph Loop for Reading: Beating GPT 5.2 with a 4k Context Window (and 4 GPUs) I built a Chrome extension that lets an LLM “see” tweets Fighting Blog Comment Spam with Qwen3 and Ollama Make a web page screenshot service Automatically remove wordiness from your writing I found Security Vulnerability in your web application My favourite Google Cardboard Apps O(n) Delta Compression With a Suffix Array Finding Bieber: On removing duplicates from a set of documents Let's read a Truetype font file from scratch A Quick Measure of Sortedness My thoughts on various programming languages A little VIM hacking
How to detect if an object has been garbage collected in ...
2020-05-25 · via Steve Hanov's Blog

If you are writing an application in Javascript, soon you will have to worry about memory leaks. But it is difficult to even know if a memory leak exists. This handy method can help.

WeakMap

At first, you may think that WeakMap will do it. WeakMap/WeakSet will hold onto things for you, but don't prevent an object from being garbage collected. The instant an object is GC'd, it is removed from the WeakMap or WeakSet.

So, the obvious solution is to check if an object is still inside the WeakMap. If it is missing, it has been GC'd. This won't work.

The problem is that WeakMap and WeakSet are designed so that you cannot get at what's inside without already knowing it is there. In order to lookup an item, you need to already have that item. These collections don't even have a length method.

To check if an object is inside of a WeakMap, you must already have a reference to it, and therefore you are preventing it from being garbage collected.

So, what good are they? WeakMap is best used to link objects together. For example, if you have a bunch of <img> elements and you want to associate some data with them, you could simply do img.myextraproperty="blah". But your IDE may complain because the HTMLImageElement does not have this property. Instead, you can use WeakMap. If the extra property is a single value true then use a WeakSet.

The Real Solution

Some browsers, including Chrome but not Firefox, have the ability to check the amount of Javascript memory used. So the solution to test if an object is there, is to make it sufficiently large so that it has a noticeable impact on memory.

In the code below, I use a WeakMap to associate a 1 gigabyte object with whatever you pass in. When the object is freed, and the garbage collector is run, you would expect at least 1 GB of memory to be freed as well. That is what the code checks for. The process takes at least 10 seconds, because it seems that Chrome only runs the garbage collector every 10 seconds.

View on CodePen

/** Determines if an object is freed
@param obj is the object of interest
@param freeFn is a function that frees the object.
@returns a promise that resolves to {freed: boolean, memoryDiff:number}

@author Steve Hanov &ltsteve.hanov@gmail.com>
*/
function isObjectFreed(obj, freeFn) {
  return new Promise( (resolve) => {
    if (!performance.memory) {
      throw new Error("Browser not supported.");
    }

    // When obj is GC'd, the large array will also be GCd and the impact will
    // be noticeable.
    const allocSize = 1024*1024*1024;
    const wm = new WeakMap([[obj, new Uint8Array(allocSize)]]);

    // wait for memory counter to update
    setTimeout( () => {
      const before = performance.memory.usedJSHeapSize;

      // Free the memory
      freeFn();

      // wait for GC to run, at least 10 seconds
      setTimeout( () => {
        const diff = before - performance.memory.usedJSHeapSize;
        resolve({ 
          freed: diff >= allocSize, 
          memoryDiff: diff - allocSize
        });
      }, 10000);
    }, 100);
  });
}

let foo = {bar:1};

isObjectFreed(foo, () => foo = null).then( (result) => {
  document.write(`Object GCd:${result.freed}, ${result.memoryDiff} bytes freed`)
}, (error) => {
  document.write(`Error: ${error.message}`)
})

How I use it

I use this method as part of my test suite for Zwibbler, my Javascript drawing app. It has a destroy() method that is supposed to remove all resources. But occasionally, I would have some event listener that was not removed, that would keep a reference to the entire application. So when using it inside something like React or Angular, where it can be repeatedly shown and hidden by the view framework, it is vitally important that resources be completely freed.