How to release ressources for KTX2 textures

After further investigation, there definitely appears to be a leak, but its over in the Web workers that do the WASM work, so it looks like it doesn’t show up in the performance.memory traces from the main thread. Tracking that down and fixing it will be one workstream, but we’re also considering another feature that would allow you to tell the Engine type to let go of its loader resources altogether, which might be helpful for memory consumption in the long term and can certainly be used as a workaround for the leak in the immediate term (by periodically releasing and recreating the KTX2 loader workers, which gets rid of the leaked memory).

ThinEngine.MinimizeMemoryFootprint by syntheticmagus · Pull Request #11442 · BabylonJS/Babylon.js (github.com)

Using this as a workaround, I was able to confirm that I could run for 25 minutes and over 300 iterations without the overall memory footprint continuing to grow. A little off the wall, but just wanted to keep you updated since this is the thread that got us looking at this. :slight_smile:

3 Likes

Thank you all for your amazing support, I’m very glad if I could help finding memory leaks in here.

@syntheticmagus Is there already a test version of your workaround which I could test in my project?

1 Like

I changed the model to the GLTF with “standard” textures - https://playground.babylonjs.com/#KNCTDK#11 - and it goes endlessly at my poor old laptop :slight_smile:
What I would suggest as possible (or temporary) solutions:

  1. Your model has a lot of 4K textures. Are they really needed for visuals or you may downscale them to 2048 or even 1024?
  2. You may try to load with GLB just only geometry and materials and then load needed textures async.

To have the ktx2 decoder do its work in the main js thread, set BABYLON.KhronosTextureContainer2.DefaultNumWorkers = 0;: that will disable the worker thread pool.

Doing so, we can indeed see that the snapshots are growing:
image

The culprit is the msc basis transcoder module:

It seems the heap used by the component is growing indefinitely…

We already had some problems in the past with this module (see "Cannot perform Construct on a detached ArrayBuffer" error when using msc_basis_transcoder - Giters).

Are you able to encode your textures in UASTC instead of ETC1S? We use some special wasm modules to handle UASTC->BC7/ASTC/RGBA so it could be a workaround (also, they are way faster to transcode than msc_basis_transcoder).

We may not end up adopting it, or the form may change; but if you really want to try my current workaround you can pull the branch from my PR and use the Engine’s new MinimizeMemoryFootprint() method periodically to cause the Engine to discard static resources, including the KTX2 worker pool. However, there’s a lot of other great advice that’s been added to this thread, too, so I’d probably only try that as a last resort. :slight_smile:

Thx again for all your great tips.
At first we will try to adjust the compression mode (UASTC), since we already have another issue that could probably be related to the ETC compression:

I will keep you informed.

2 Likes

Hi there @TheHOF ! Just checking in to see how’s your issue, has it been solved? :slight_smile:

Hi @carolhmj,
we managed to solve our application by reloading the page when materials from a different GLB are required, since this was the only way to release the ressources.
It works fine for us and we know how to work this around in the future, but I guess the original problem is still there.

3 Likes

I’d like to add something to Markus’s comment:

The mentioned solution using a page reload is actually a rather horrible workaround and we’d really appreciate if the underlying memory issues would be tackled in Babaylon JS at some point to allow us better control of the whole memory management by e.g. releasing resources which are not used anymore to free up memory etc.

@bghgary do you know if there were any progress made on the ktx loader itself ?

There has been some movement, but I’m not sure it will address the memory issues. Notably, the msc_basis_transcoder WASMs are now generated from the basis github instead of KTX as noted here:

Releases · KhronosGroup/KTX-Software (github.com)

NOTE: that msc_basis_transcoder is deprecated and will be replaced by the transcoder wrapper from the Basis Universal repository.

We can try updating to see if there is improvement.

1 Like

Sorry for the delay. It’s been a busy month.

Issue filed: KTX decoder appears to leak memory each time it is used · Issue #11839 · BabylonJS/Babylon.js (github.com)

1 Like

I found two issues with the KTX code and this should fix the memory issues people are seeing.
Once this PR (Fix memory leak and incorrect data copy in KTX2 by bghgary · Pull Request #11846 · BabylonJS/Babylon.js · GitHub) is merged and deployed, we should be good. Sorry for the wait.

3 Likes

I’ve ran the original PG with a count of 3000+ now and haven’t run out of memory. It does appear there is still a very small memory leak which we can tackle at a later point.

1 Like

Hi @bghgary,
I checked the original PG example and it broke on the iPad 12.9, Safari V15 (via Browserstack) after the 4th run.
It seems to work fine on the same device with Safari V14 though.

I was running on a PC. Does it at least work on a desktop?

Yes PC was fine, tried it on my laptop (Win10 / Chrome)

1 Like

The reason why this is failing on iOS is the same as the other thread. I think we can consider this issue resolved. Let me know if you disagree.