WebGL OOM errors during startup

Hello,

We are logging errors from our WebGL game and one of the frequent errors is an out-of-memory crash. It often happens immediately after the game is launched, while loading initial content.

Example error (desktop and mobile):

Could not allocate memory: System out of memory!
Trying to allocate: 16776956B with 16 alignment. MemoryLabel: Serialization
Allocation happened at: Line:72 in
Memory overview

[ ALLOC_TEMP_TLS ] used: 24956B | peak: 0B | reserved: 4194304B
[ ALLOC_DEFAULT ] used: 217439794B | peak: 217439794B | reserved: 221076698B
[ ALLOC_TEMP_JOB_1_FRAME ] used: 0B | peak: 0B | reserved: 0B
[ ALLOC_TEMP_JOB_2_FRAMES ] used: 0B | peak: 0B | reserved: 0B
[ ALLOC_TEMP_JOB_4_FRAMES (JobTemp) ] used: 0B | peak: 0B | reserved: 524288B
[ ALLOC_TEMP_JOB_ASYNC (Background) ] used: 142B | peak: 0B | reserved: 3407872B
[ ALLOC_GFX ] used: 8438503B | peak: 8438503B | reserved: 8457864B

Could not allocate memory: System out of memory!
Trying to allocate: 16767284B with 16 alignment. MemoryLabel: Serialization
Allocation happened at: Line:72 in
Memory overview

[ ALLOC_TEMP_TLS ] used: 24956B | peak: 0B | reserved: 4194304B
[ ALLOC_DEFAULT ] used: 251034158B | peak: 251034158B | reserved: 254670967B
[ ALLOC_TEMP_JOB_1_FRAME ] used: 0B | peak: 0B | reserved: 0B
[ ALLOC_TEMP_JOB_2_FRAMES ] used: 0B | peak: 0B | reserved: 0B
[ ALLOC_TEMP_JOB_4_FRAMES (JobTemp) ] used: 0B | peak: 0B | reserved: 524288B
[ ALLOC_TEMP_JOB_ASYNC (Background) ] used: 142B | peak: 0B | reserved: 3670016B
[ ALLOC_GFX ] used: 8536807B | peak: 8536807B | reserved: 8556168B

Project details:

Unity: 2022.3.62f2
Addressables: 1.22.3
Platform: WebGL

Compression: Brotli
Decompression Fallback: Off

Initial Memory Size: 32 MB
Memory Growth Mode: Geometric
Maximum Memory Size: 2048 MB
Geometric Memory Growth Step: 0.2
Geometric Memory Growth Cap: 96 MB

IL2CPP: Fast runtime
.NET Standard: 2.1

Shader variant loading settings:
Default Chunk Size (MB): 16
Default Chunk Count: 0

Addressables:

Bundle sizes:
defaultlocalgroup_assets_all ~3.4 MB
lazyloading_assets_all ~6 MB
unitybuiltinshaders.bundle ~19 MB

Bundle Mode = Pack Together

The ~16 MB allocation size appears repeatedly. We are wondering if this could be related to shader variant loading, bundle decompression, or Addressables dependency deserialization.

Any suggestions would be greatly appreciated.

whats the difference between when it does and when it doesnt?

example:

I have most of a basic minecraft game set out, if i compile it and run it in webgl, it works - huzzah
moment i mine and change anything, its running out of memory. because its just that close

In our case, the OOM usually happens during startup while loading the initial content, before the player can interact with the game. It can also happen later when loading maps through Addressables, but startup is by far the most common case.

We’re trying to understand whether this is something we can improve with Unity settings/content optimizations, or whether it’s simply expected behavior on lower-end devices and browsers with stricter memory limits.

From our testing the game typically uses around 500 MB of memory during gameplay, but we have seen it temporarily jump above 700 MB when loading a new map, especially if the previous one has not been fully unloaded yet.

Only a small percentage of players are affected, which makes us wonder whether these users are simply running on devices/browsers that don’t have enough available memory for the additional allocations during loading.

One thing that stands out is that the failed allocation is almost always ~16 MB. We noticed that Unity’s Shader Variant Loading setting (Default Chunk Size) is also set to 16 MB (the default value), while our unitybuiltinshaders.bundle is ~19 MB. Has anyone experimented with changing this value (e.g., 4 MB or 8 MB) for WebGL projects, or seen MemoryLabel: Serialization OOMs related to shader loading or Addressables bundle deserialization?

We’re particularly interested in hearing whether people have had success reducing these startup OOMs through Unity configuration changes, or if this is generally considered unavoidable for a subset of low-memory WebGL clients.

I’d suggest to try the following workaround, at the very least it would allow you to hook into the before/after and log exactly how much memory is being used already prior to loading the content. That’s assuming you do that loading right away in Awake, OnEnable, or Start.

The idea is simple: launch the build into an empty pre-launch scene. It needn’t even have a camera. Just a single script that loads the actual “first scene”. Optionally it could call GC.Collect() just to free up as much memory as possible. Then you can perform your “current active memory” logging.

Worth noting: you cannot call LoadScene from Awake, and probably not from OnEnable either. It needs to be deferred to Start or possibly even the first Update.

You may also want to check the Player settings, and raise the initial allocated memory size according to what the game needs at the minimum. If the player needs to cycle through several allocations it makes OOM all the more likely. Some developers even go so far as to allocate the maximum amount (eg 2048 MB, or more dependent on use of WebAssembly 2023), but that bears other risks.

Since you say “devices”: on mobile, iOS specifically, browser tabs have severe memory limitations. iOS watchdog might just kill a browser tab if it consumes > 500 MB memory, or takes 10-15s to load something which may lead watchdog to assume the tab is unresponsive.

Worth noting that scene or asset loading always spikes memory pressure. It’s sort of like unzipping a 100 MB file, that unzipped data has to live in memory too before it can be written to disk.

When you mention “previous scene not fully unloaded” - how do you determine that? A LoadScene in single mode will always destroy the previous scene and its contents first, then start loading the next. If anything is still “loaded” at this point, it’s likely either the addressable/bundle assets, otherwise it could be a leak.

For additive loading, it’s highly recommended to skip at least one frame after unloading before loading another additive scene. A forced GC.Collect() and/or UnloadUnusedAssets in between (skipping two frames so these two truly run in-between) could also improve odds by decreasing memory pressure.

That’s likely an artifact. It’s always the same size everywhere you look. It may not even point to an OOM but some other sort of (likely still memory related) crash. For instance a driver bug or hardware failure ie switching between integrated GPU and discrete GPU on laptops is a common source. But it could also come from Unity trying to allocate the next 16 MB depending on the web player’s memory allocation settings.

On top of those great suggestions Id also suggest trying to get more info on what links fails, maybe some maps are just too big, maybe some devices too petty (IOS yes, you), see if you can narrow down cluprit areas and devices.

I don’t. That was an assumption based on the observed peak memory values.

After doing some more testing, I realized that the large memory spike during map transitions was not caused by the previous map not unloading correctly. The main reason is that one of our maps uses Unity Terrain, trees, more materials and this single map increases memory usage by around 250 MB. Other maps usually add only around 20-50 MB on top of the base memory usage.

So the map with terrain is a separate optimization issue that we will investigate (possibly replacing terrain with meshes, reducing terrain layers, vegetation, etc.).

However, going back to the original OOM issue: based on additional testing, most crashes seem to happen much earlier, during initial content loading. At that point the game memory usage is around 360 MB. When we also load our lazy-loaded assets, memory usage increases to around 450 MB.

This makes us wonder if the issue is simply that some users’ browsers/devices cannot provide enough available memory even at the 350–450 MB range, or if there is something else we should investigate (for example WebGL heap growth, temporary allocations during bundle loading, or Addressables loading behavior).

Would an OOM at this memory range be expected on some percentage of WebGL clients (especially mobile browsers), or does it usually indicate another underlying issue?

I confess its been a while since I used 2022.3 for a web build, what build settings do you have? I seem to recall some of them produce higher memory loads than others, and there was a time when it could barf 00M even when it wasnt for a blank screen (but I dont remember when exactly that was)

if you run it on your pc, what does chrome show as the memory use for that browser tab?

I’ve only checked the memory usage reported by the CrazyGames QA tools so far.

I already listed some WebGL and memory-related settings earlier in the thread, but if there are any specific Player or Build settings you’d like me to check, let me know and I’ll post them.

Personally, I’ve never experienced any loading issues myself. Since only a very small percentage of players are affected, I’m still trying to determine whether this is an underlying issue on our side or simply users running the game on low-memory devices/browsers.

On mobile? For sure. It heavily depends on the browser and the device, but also how it’s being used. On Android users have “too much freedom” to install all sorts of background tasks, willingly or without knowing. Those eat up memory. The OS is pretty aggressive to clean things up and that sometimes forces apps to close due to memory pressure. Happens with any app, and particularly on older devices.

For instance the Brave browser on my old 6th gen iPad is notoriously unstable when I scroll through pages or switch tabs. It starts by flickering the content, at which point I already force quit it. Any tab switch after that could be an immediate crash. But it’s still better than Safari which after the last major iPadOS update became excrutiatingly slow, even scrolling. It’s unfathomable to me how that is not clearly a software defect in the “planned obsolescence” sense.

But I digress. The answer is: yes, browser crashing due to OOM will happen to mobile users.

You may find that most affected users have either outdated devices, those locked into a specific major OS version and/or those with constrained RAM compared to newer devices. Case in point: my iPad gen has 2GB, the next gen has 3GB like most others following that.