Webgl never releasing memory

Hi! I’m not able to release memory in webgl.
The memory allocated when I download an assetbundle is never released. I’ve tryed everything I’ve found; destroy objects, unload assetbundles, disposing the request, unload unused assets, cleaning cache… Nothing works. Even if I change scene, memory is still allocated.
If I use the profiler (both in editor and autoconnected), I can see how memory increments and decreases when I unload things, but then, in the browser it’s as if the garbage collector, is never, never working.
I’m in Unity 5.5.1f and it’s happening, both in Chrome and in Firefox (last versions).
Any help, please?
I’m quite desperate…

Garbage collection only happens inbetween frames on webGL.
On webGL memory management is a bit different than a build for standalone.
You should read up the blog(s) and manual about webGL memory.

Like this one:

Do mind that this blog post is old and contains old API. Use UnityWebRequest for downloading bundles and not WWW.
The WWW class will be deprecated/obsolete.
Also a lot has changed in the meanwhile between 5.5.1 - 2017.3.1.
Try to keep Unity up to date as much as possible especially for webGL it is good to keep up with the newer versions due to fixes and optimizations

My advice would be:
Try to keep the bundles as small as possible or even split them up in multiple bundles so that the browser doesn’t have to allocate a lot of memory as download buffer for the bundle.

That’s probably the best advice you could get. Gap between these two versions is huge both in performance and stability. You should do everything to keep Unity version up to date. WebGL is rapidly improving and every major unity update brings something new.

When we started, it was easier to keep that Unity version than change it. Now I’m not so sure … In any case, thank you very much @MaskedMouse and @andrzej_cadp for the advices. I’ll keep them in mind!

The blog post is a bit old but most of it still apply to recent releases. One thing I should mention is that GC.Collect() works now, the only difference compared to other platforms, is that the garbage collection happens with one frame of delay.

GC.Collect() may work in theory but on practice it doesn’t, not even on scene load. (Tested in Unity 2017 and 2018 b7,8,9)
I have reported a bug some time ago (Case 1004043)

thanks for that bug report. I have started looking at it.

I think GC.Collect per se actually works. IIRC your repro:

  • allocates a big chunk of memory in one go

  • deallocate

  • garbage collect

  • tries to re-allocate another block of the same size.

The problem is that this relies on the fact that no other block is allocated between 3 and 4. If another allocation sneaks in, then the free block becomes smaller/fragmented. From what I have seen, we do have some internal engine allocations that happen every frame. Although I think most of them are temporary, they might fragment memory.
I really think this is something we should fix, however, based on this consideration it would be interesting to:

  • allocates a big chunk of memory in one go

  • deallocate

  • garbage collect (either swap scene or call GC.Collect and wait at least one frame)

  • allocate a lot of smaller blocks that altogether approximately amount to the size of the block in #1

If this does not work, then we have a GC problem.

I hope this makes sense.

1 Like

Ok, I have attached a slightly changed TestScript from repro project.
In first scene I allocate 150mb and even call GC.Collect() after.
Then in second scene I call “for” loop allocating 10mb per iteration.
The result is: 150mb allocated in first scene, then in second scene it crashes after iteration 5, so it wasn’t even able to allocate 70mb.
Memory size is default 256mb.

Conclusion: Once the memory is allocated in WebGL it becomes unusable for future allocations.

3430423–271047–TestScript.cs (1.26 KB)

Thanks, I’ll take a look at it on my side.

What is the correct way to Unload\Release Unity in WebGL build?
Application.Quit() dos not work.
We have a SPA with Unity in a tab. When we are switching tabs,Unity instance does not get destroyed and consumes a lot of memory. Any suggestion?

Would it be possible to manually track memory usage for specific objects, kinda like using C? This way we could keep track of objects that would be prone to GC issues. Could calling GC manually help in certain situations?

Marco, any insight on this? It seems we’re struggling with the same issue.

@Marco-Trivellato any news in this subject??

3 Likes

@Marco-Trivellato , is any work done recently in this area?
It seems that WebGL is falling behind all other new ‘cool features’.

We have a mechanism for this in 2019.1, check this post .

I believe there is a fragmentation problem so large allocations might fail because of that. We still need to investigate.

which cool features?

I think the new memory profiler might help with this but personally I haven’t used it yet.

1 Like

I did not hear any mentioning of WebGL on Unite LA 2018 nor Berlin 2018.
It would be nice to have some new intermediate or advanced tutorials on Unity 2018/2019 WebGL.

I have this problem again since 2018.3

Resources.UnloadUnusedAssets();
GC.Collect();

This works in a standalone bulids.
In WebGL the memory size only goes in one direction. Up and Up and Up… (And it already start with a very high value…125-128MB. It was ~15MB in 2018.2)

any idea why? I did not have this problem in 2018.2