Hello!
When doing some memory “profiling” in our project that uses Babylon I found that Chrome is reporting a lot of memory being used to store strings that seem to represent PBR shaders.
I know that Babylon creates a lot of shader variants with the PBR shaders, so I quickly tested some artificial cases to see how bad it can get, and it wasn’t hard to get into the hundreds of megabytes of strings, which seems to be mostly these strings.
I then tried tracking down where shader source code is stored in strings, and found a couple of places:
- The keys to the
_compiledEffects
map on the Engine - In
Effect
class: _fragmentSourceCode
_vertexSourceCode
fragmentSourceCodeBeforeMigration
vertexSourceCodeBeforeMigration
I made a Playground example that creates an artificial, but not unrealistic, case for us, where we basically just automatically cycle through a bunch of light configurations to generate shader variants. It also estimates the worst-case memory usage of the variables listed above, which it prints out into the console every 4 seconds.
Screenshot with Chrome’s memory profiler showing the shader code
Now in that specific example, I reach about 16MB of strings after not too long (counted from those variables, Chrome reports more strings being used). It’s not too much, but still noticeable on mobile devices. But an important thing to note is that we usually have several variants of PBR materials (regardless of lights) due to being sourced from different GLTFs, meaning the number multiplies quite fast:
- In an artificial test case we have, we reach upwards of 400MB of these strings (again, Chrome reports slightly more, but there’s other data as well of course). They’re spread over 277 shader variants.
- In a realistic scenario, we easily reach 100MB of these strings (87 variants), which is a big portion of our budget on some mobile devices. However, it’s not unreasonable for some of our user journeys to double or quadruple that number if they play around with the light configuration.
If you have any issues with my method of measuring this, please let me know! I don’t know the inner workings of Babylon, and I’m not that used to the web environment either!
I wanted to write this just to make sure you were aware of it, and maybe you can point us in the right direction to alleviate some of these issues:
- Is there a way to purge the cache of unused shaders somehow?
- Is there a way to discard the source code copies, and maybe use a hash for the
_compiledEffects
array, to reduce the memory footprint?
Or if you have any other ways to otherwise reduce this memory footprint, I’m all ears
If the answer is no to those questions, then we might look at creating a PR (or if you want to do it) if you think it sounds like a good idea.
Thanks in advance,
Tore