iOS Large Memory Usage = Apparently Feature, Not a Bug?

Well, if you have been following the iOS Large Memory Usage thread , the issue of which Astrogun internally called the ‘Titanium Moth’ bug, the latest reply from Unity via Apple is essentially that it is a feature, not a bug:

iOS 12 large memory usage page-4#post-4271797

This ‘feature’, known to ‘more accurately’ double or even quadruple a Unity game’s memory footprint on iOS/tvOS, hitting memory limits and causing apps to crash, for over half a year now— when they previously worked fine, means that, while we were able to ship a game that looked better on older hardware (even four year old hardware) two years ago, now we must curtail what is possible with Unity on these platforms to get it to work on even newer hardware today. By a lot. A lot, a lot, a lot.

Unity has either waited until the March 1st Apple deadline requiring all developers use iOS 12 or Xcode 10, forcing them to face this memory ‘feature’ and knew they had no solution (since perhaps when this bug first emerged around Summer 2018), or they were trying up until today to find a solution, or both. I’d like to give Unity the benefit of the doubt here and think that they were trying right up until the limit. Unity wouldn’t leave us out to dry like this would they?

Now essentially it seems the word is, Apple isn’t budging on this. Because they’re Apple. So that effectively means Unity must instead.

I hope Unity isn’t just ‘closing this bug’ and moving on like they’re eager to do with the thread. This has to be addressed fundamentally in the engine itself. Perhaps they must rethink compression methods on iOS/tvOS now to stay under Apple’s new memory limits? (this is a rhetorical question…)

The way the thread was addressed today and closed by Unity is, with all due respect, very off-putting to say the least. It sort of felt like "since we absolutely must say something today now that the deadline has passed and there’s absolutely nothing you can do about it, our answer is: we have no answer so deal with it."

Meanwhile, Unity is busy posting dog photos on Instagram.

I know a lot of other developers were affected by this memory quadrupling ‘feature’ that breaks parity with other platforms, and they can’t be happy by this news…

To Unity, this is extremely disappointing and unbecoming. But also not unexpected.

8 Likes

As far as I can tell, the article that ScottF linked to is very new. Maybe it was created as a direct reaction to this issue. It may have some clues as to how we should approach optimization for 10.1.

FYI I was able to submit a new build today (March 1) built with 9.4.1. How long that will be allowed is ambiguous.

@ScottF - Are we able to take advantage of all these Metal features mentioned in the article? And is that true for images attached to UI Images?

Designate resources as volatile when possible. Use MTLPurgeableState.volatile and setPurgeableState for textures and buffers whose underlying memory could be discarded under low-memory conditions, and subsequently recreated or reloaded as needed. This allows your app to keep a cache of idle resources in memory while avoiding counting them toward the memory limit.

Use memoryless texture storage for temporary render targets. MTLStorageMode.memoryless avoids allocating regular system memory, allowing apps to store the contents of temporary render targets directly in tile memory on the GPU.

Use Metal resource heaps. MTLHeap allows multiple Metal resources to be backed by the same memory allocation. For instance, you can use resource heaps when transient resources are produced and consumed for each frame but aren’t all used together. Those not used together can share the same memory, backed by a heap.

Is it possible to select which graphics engine to use (Metal vs OpenGL) at run time? In our case (and I realize this may not be helpful for others) the most impacted devices are older iPhones and iPads - at launch, could we choose to have those devices use OpenGL and newer devices use Metal?

One more: We are currently using 2017.1.3p1 - is Metal memory handling in some way better in later versions of Unity?

I was about to create a new thread about this and tag the main members of the last discussion since Unity decided to lock the thread from further discussion so we could no longer discuss it (good old Unity).

Anyway, the old “iOS now reports the memory usage properly” reason we’re giving makes no sense to me because:

A. My game doesn’t crash when built with the old Xcode version, so if it was ‘reporting’ that was the issue, my game would still use too much ram and cause the the game to crash, but I’d see no reason for it as the memory usage would be well under the max limit (as reported - apparently incorrectly)

B. On old Xcode, my game uses almost exactly the same amount of memory as my android version - which makes sense. But on new Xcode it triples.

So basically, if I’m to understand what is supposed to be happening it’s that my game has always used 3x as much ram than the same game on Android and because it’s now being reported correctly, the device is shutting my game down?

Makes no sense to me.

5 Likes

That’s what Apple is saying, more or less:

@ScottF Is there a technique like this one to query Metal about how much “Metal memory” we are using?
task_info is giving me much smaller memory numbers than the gauge and I’m trying to print out memory usage at various points in my code to better identify hotspots. @Xander-Davis is this thread OK for questions like this (and the ones I mentioned above) or would you prefer I move them to another thread.

@jtokash - fine with me. In my opinion, it was a mistake for Scott to lock the previous thread because clearly this will remain a major issue, seems to be unresolved from our end (Unity’s customers), and the discussion amongst developers needs to be ongoing with each other and Unity.

2 Likes

I agree Xander. If this is going to be the new normal, we’re going to need some help adapting. @_Paulius @martonekler @ScottF , can you answer the optimization/analysis questions I posed above? Repeated/clarified here for convenience:

  1. Is there c# or objective c code we can use at runtime to find out how much metal memory we are using? I’m trying to litter our code with profiling to find the best areas to tackle and the standard objective c solution is not counting that memory…

  2. Is it possible to set the graphics engine to use (Metal vs OpenGL) at run time? In our case (and I realize this may not be helpful for others) the most impacted devices are older iPhones and iPads - at launch, could we choose to have those devices use OpenGL and newer devices use Metal?

  3. For those of us using 2017.1.3p1 or an older Unity version - is Metal memory handling in some way better in later versions of Unity? Should we upgrade as part of the solution?

  4. The Apple article that @ScottF linked to mentioned some specific areas to investigate - Are these capabilities available to Unity developers? If so, what versions of Unity should we be looking at?

Designate resources as volatile when possible. Use MTLPurgeableState.volatile and setPurgeableState for textures and buffers whose underlying memory could be discarded under low-memory conditions, and subsequently recreated or reloaded as needed. This allows your app to keep a cache of idle resources in memory while avoiding counting them toward the memory limit.

Use memoryless texture storage for temporary render targets. MTLStorageMode.memoryless avoids allocating regular system memory, allowing apps to store the contents of temporary render targets directly in tile memory on the GPU.

Use Metal resource heaps. MTLHeap allows multiple Metal resources to be backed by the same memory allocation. For instance, you can use resource heaps when transient resources are produced and consumed for each frame but aren’t all used together. Those not used together can share the same memory, backed by a heap.

  1. Our games use Unity UI and UI Images heavily - anything in particular we should keep in mind with regard to Metal?

Thanks for any information you can provide!
John

1 Like

This one is this : https://docs.unity3d.com/ScriptReference/RenderTexture-memorylessMode.html

Also Memoryless Depth in the player settings.

Although these are probably not available in 2017.1

Thanks @AcidArrow !

Edit: I removed this post - it was my attempt at reverse engineering the XCode Memory Gauge number. My technique worked for one project, but I’ve since tested it in 2 other projects and it was very far off. I would still LOVE a way to get that number from code.

2 Likes

So I’ve just performed a quick test: how much ram is an empty project taking?
With nothing out there it was about 80+ MB (Xcode 10.1 / iOS SDK 12.1, Unity 2018.1.2f1).

Am I missing some sort of a setting here? Shouldn’t the memory usage be around 20MB?
Could anyone try making an empty project on their machine just like that? Maybe something
is wrong with my mac?

1 Like

Also, Unity: Project Tiny

^^^ this seems massively ironic.

I’ve made a few different memory testing projects here are some WIP conclusions. I hope they help others:

  • If you are loading textures make sure they are marked as nonreadable. Readable textures take up twice as much memory (regardless of iOS version, XCode version). Pass true as the second param to Texture2D.LoadImage to save that memory. Or if you are loading from Resources, make sure the Read/Write enabled box is unchecked.
  • An empty project built with Unity 2017.1, XCode 9.4.1, run on iOS 11 shows about 35 MB in the XCode memory gauge. Same project built with Unity 2017.1, XCode 10.1, iOS 12 show about 95MB in the XCode memory gauge. That’s 60MB of new overhead right off the bat.
  • In my controlled memory tests, loading Texture2Ds via Resources(Resources.Load) and Streaming Assets(Texture2D.LoadImage) does not cost more (according to the XCode memory gauge) in iOS 12/XCode 10.1.
  • That said, one of our games is taking up 164 more MB under iOS 12/XCode 10.1. As I mentioned earlier, 60MB of this is “expected” for any Unity project. I have not yet established where the other 100MB is coming from and if it is somehow tied to images.
  • As previously mentioned, the cap for XCode gauge memory before things start going haywire on an iPhone 6 plus is now 600MB on iOS 12, so I’m still looking to reduce the 164 MB increase.
  • Reminder: if you are testing XCode 9.4.1 and 10.1 from the same XCode project/folder, make sure you do a Clean when you switch between XCode versions. If you don’t, sometimes XCode will just use the last compiled version.
3 Likes

60mb extra is crazy. Thanks for the in depth information.

It ooks like apple is somewhat acknowledging this in todays announcement:

March 27th is the absolute deadline for requiring ios 12 sdk suppor, which as we know potemtialluy brings memory related crashes.

Whats interesting is at the bottom of this page they mention this and give a link to apply for an entitlement to use the old memory system.

Understanding Changes in Memory Accounting
iOS 12 and tvOS 12 require apps to use memory far more efficiently than before. If you have difficulty reducing your app’s memory requirements, contact us to request an entitlement for your app to use iOS 11-style memory accounting.”

Check it out.

3 Likes

Wow. So does that mean an app can actually use the old-style memory accounting and avoid memory-related crashes? Or is that just for review purposes…but doesn’t sound like that.

1 Like

Judging from the wording it looks like you can at least apply for a kind of exemption.

It makes sense because this is an actual issue, and developers have no choice but to use Xcode 10 in a few days. So i dont see how they could justify that upgrade to a setup that crashes apps.

I wish this whole thing had been more transparent. And i wish Unity had also left the previous thread open, because there was a lot that still needed to be discussed about it. The way that it was shut down without warning left me feeling without support.

5 Likes

We have the exact same problem. We released an update a week ago buildt with Xcode 10 and we immediately got reports from iPhone 5s,6 and 6 plus users that the game now crashed. Thats when i found the previous thread and realized this is a huge issue. Our game has double the memory when buildt with Xcode 10, so i’m not buying the explination “On iOS 12 and Xcode 10 Apple’s memory reporting tools has been updated to more accurately track memory footprint”

I’ve applied to Apple for an exemption today.

1 Like

If you don’t mind, let us know how that goes