I am developing a voxel engine in Javascript using Threejs, and I've run into some memory usage problems. The intended environment is within an Electron application, which means I can launch the program with flags (--expose-gc
) that enable manual garbage collection with gc().
I noticed that when running the gc() function, much less memory was freed compared to when I clicked the "collect garbage" button in the Memory section of Chrome's developer tools. For example, if the program initially used 2000 MB of memory, after gc() it would free up to 300 MB, but after clicking the aforementioned button, it would free up to 600 MB more, making it about half of what it originally was.
After some digging, I also found out about the --gc-global
flag. This would've been perfect, since it behaved in the same way as a manual gc did, but it ran multiple times per second, making my program extremely laggy. I tried controlling the gc rate with --gc-interval
, but it didn't affect it at all.
I also found this answer that talked about ProfilerAgent.collectGarbage();
, but it always threw a reference error. Additionally, the flag it provided (--debug-devtools-frontend
) wasn't recognised by Chrome. That, and the fact that I could find very little info on it outside of the answer, lead me to believe that it's an obsolete feature.
I also profiled the memory usage from the developer tools, and surprisingly, it was much lower compared to the value that Task Manager showed me: it seemed to be unaffected by the leaking memory. This has made it nearly impossible to determine where the memory could be leaking from.
I should also make it clear that while Chrome does garbage-collect on its own, it's far too infrequent, and it rarely does a full gc, meaning that memory usage is about twice of what it could be.
In summary, is there a way to trigger a full garbage collection from either Chrome or nodejs/Electron? Obviously, I'm not concerned about cross-browser support, so any advice would be appreciated.
It turns out that self.gc
only collects garbage in the thread/worker it was called from. Running the function in all of my workers freed as much memory as the developer tools garbage collector did.