WebGL memory increment issue and crash on iOS

So after some testing with the mobile version of our WebGL application, I found some issue with automatically increasing WebGL memory on iOS.

Whenever the memory needs to increase from 256MB to anything higher, to lets say, 300 to 500MB, the browser tab crashes and does a force reload. The interesting thing is, when publishing the app with a 512MB base memory instead of 256MB, the app loads fine, takes longer to crash as it does not need to increase the memory as quickly.

This happens on all iOS devices I have tested on.

The problem here is that some other mobile (android) devices cannot reserve 512MB at start and will crash without loading. So at this point in time, its a choice between a quick crash on iOS or a application that doesn’t work on other mobile devices.

Another problem with these memory crashes on iOS, is that the browser does an instant page reload without giving an error message. This makes us unable to inform to the user that an error occurred and leaves the user guessing on what happened.

Are these known issues and is there a workaround or fix possible?

When you have a memory budget of 256 MB and the app you run exceeds that, consider this the same issue as running out of free device memory if you were making a native app. You‘re strictly required to ensure the app runs within that memory budget, be it device memory or browser tab memory.

What you need to do is to determine why memory usage spikes too high for a short time (GC alloc, resource load) or continuously increases (not unloading resources, memory leaks).

As for workaround, you can also set 384 MB or any number. However that will just alter how long the app will run before it eventually crashes. If I understood you correctly, it even crashes with 512 mb memory budget. So there‘s your problem, not the budget itself.

I think you misunderstood the issue. iOS can handle 512MB memory fine, but only if it is set as startup memory. If the startup memory is set to 256, it is not able to increase to anything higher, not 512, not 384. This makes me believe that there is an issue with increasing the wasm working memory size on iOS.

When 512MB is used as the startup memory, our application doesnt work on some android devices.

Maybe a temporary solution is to set the startup memory depending on the platform. Is it possible to change the startup memory from the Unity JavaScript WebGL Loader, or would that require seperate builds?

1 Like

It was my understanding that the startup memory is a hard limit but it is not. However, growing the memory is something that can fail at any time (due to the requirement of “contiguous” allocation). That is why we considered it to be an upper limit because expecting the browser to give you the extra memory you need right now is simply too risky.

See here: Unity - Manual: Memory in Unity WebGL
There’s a lot of pointers and caveats attached.

So if it works with 512 mb startup but not 256 startup why don’t you try some in-between values like 384 mb? There’s no requirement for startup memory to be on the power of two scale.

Yes, everything is set up correctly and we manage our memory well. The problem is that the automatic memory increase does not work correctly on iOS.

iOS can run 512MB fine, but is not able to use 512MB memory unless it launches with 512MB on startup. When launched with lower amounts of memory, it wont increase past 256MB.

The other issue is that safari will not log any error or crash message and force reloads the page instantly.

Hi!
First of all, how can you change the base memory? I spent the morning trying to do that (Unity 2021.3) and I can’t find it.

I remember old times when it was in the .json file. To do something like you want to, I had two JSON and I decided which one to load based on device. Now I thought it should be in the config object in javascript, so it should be even easier. Did you try that?

@dinkelstefan did you find a suitable solution to this? I’m also encountering this issue.

Isn’t it detailed in the Unity manual? It used to be in there. Check Player settings (on the WebGL tab obviously), most likely it’ll be in there.

Probably not because the whole memory allocation and in particular incremental allocations in WebGL is a black box and it can fail at any time on any device for seemingly no good reason. Sometimes it’s as easy as restarting a device that constantly runs out of memory, and then it suddenly works fine.

But really the best solution in my opinion is to aggressively lower memory usage all over the board for WebGL apps and allocate the most memory you will need and can safely allocate up front (said “base memory” but I believe the term is different) to minimize or entirely avoid incremental allocations.

Also, do not rely on specifications that say “Browser X can allocate Y memory per tab” because even that is just a theoretical thing. Like an iOS device that has 4 GB of memory, it won’t be able to give all that memory to a single app. Nor does the OS consume a constant amount of memory, and depending on apps installed and device model background processes can also consume a variable amount of memory.

But at least with native apps you have a way to react to memory pressure through OS events. WebGL doesn’t give you that option, hence the recommendation to aggressively lower memory usage.

I have profiled my game and let it run for several minutes and the game never needed to extend memory usage beyond the initial 120MB that it started with. My game is pretty light-weight but for some reason on iOS running on a browser it just randomly lags and crashes.

One thing to note, within an iOS native app running on a webview, it’s running perfectly fine. There’s some memory shenanigans going on, likely on iOS 16 and up that’s causing weird issues on a browser.

1 Like

Apple has a history of not giving a f*** about anything WebGL related. Certain developments in the web space are threatening their business model. I know this isn’t helpful, just to set expectations.

Anyway, make sure you reboot the test device. If possible, reset it to firmware defaults. If the issue still persists only on that device (or other iOS devices but no Android) then it’s likely an iOS issue.

There are multiple factors that can cause an app to terminate due to memory overage, and I have investigated the following items in the past. If any of them are exceeded, the Unity app will terminate.

  • Hardware RAM capacity limit
  • Limits set by Unity build settings
  • Limit set by browser management (512MB for devices with iOS 4GB RAM, older devices may not even start with 100MB)
    *The memory value is based on the memory managed by the browser, not the memory value displayed in the Unity memory profiler, so you should refer to the browser’s debugging function or the memory API by JS.
1 Like

did you find any resolution to this problem?