Search Unity

  1. Megacity Metro Demo now available. Download now.
    Dismiss Notice
  2. Unity support for visionOS is now available. Learn more in our blog post.
    Dismiss Notice

IL2CPP build size improvements

Discussion in 'iOS and tvOS' started by David-Berger, Apr 28, 2015.

  1. PixelSquad

    PixelSquad

    Joined:
    Sep 4, 2014
    Posts:
    114
    Thanks, I agree. And I think Apple should have made this available before they started requiring people to support 64-bit on their apps. It's a kind of a nightmare for me now, I imagine many other people are going through the same :)
     
  2. Moonjump

    Moonjump

    Joined:
    Apr 15, 2010
    Posts:
    2,572
    I struggled to find any example figures for the difference IL2CPP makes to app sizes, so I put my own figures together and am now sharing them here.

    This is an app nearing completion, but still requires external SDK's adding (analytics, ads, social). I think it is quite well optimised. The app is identical in both versions, except for player settings, and made with the free version, so no build stripping.

    Unity 4.6.1, so prior to IL2CPP:

    IPA size: 19.0 MB
    Estimated App Store size: 32.8 MB
    On device size (iPhone 5): 68.1 MB

    Unity 4.6.7, built with IL2CPP:

    IPA size: 22.3 MB
    Estimated App Store size: 40.3 MB
    On device size (iPhone 5): 79.6 MB

    So not too bad, although it does push the size on the device into the realms where it is vulnerable to deletion when searching through Usage to make space on the device. Hopefully App Thinning will be supported soon.

    The big problem though is I am seeing a large reduction in performance. It ran easily at 60FPS on an iPod Touch 4th Gen before, but is very jerky now.
     
  3. JoshPeterson

    JoshPeterson

    Unity Technologies

    Joined:
    Jul 21, 2014
    Posts:
    6,920
    @moonjump

    If you are able to share your project, we're very interested in profiling to to check out the performance regression with IL2CPP. Also, we've made a few specific performance optimizations internally (specifically involving the removal of unnecessary boxing for value types) that will be available in 4.6.7p2 (scheduled to be releases on Friday of this week). You may want to give that version a try to see if the performance issues are improved.
     
  4. JoshPeterson

    JoshPeterson

    Unity Technologies

    Joined:
    Jul 21, 2014
    Posts:
    6,920
    @PixelSquad

    We do have a few more build size improvements in process now. Specifically, we're moving the last bit of metadata out of the executables and into separate files. This should avoid the unnecessary duplication of the metadata (it was previously the same information in both executable slices) and reduce the size of the metadata itself (we can convert 64-bit pointers to 32-bit indices).

    I'm not sure yet when this will land, but I would expect it within the next few weeks, so please watch the patch release notes.
     
  5. PixelSquad

    PixelSquad

    Joined:
    Sep 4, 2014
    Posts:
    114
    I often wonder if it would be possible to have a 64-bit version of mono.

    The advantages would be reduced build size (as am I right in saying the game code is shipped as part of data on mono, so only one copy of that?), reduced output time (as no need to generate CPP files from Unity -> Xcode), reduced build time (on XCode as less source files to compile), and keep the same performance as before.

    I actually checked it, and it looks like they have support for 64 bit on ios? Here: http://www.mono-project.com/docs/about-mono/supported-platforms/

    It's just an idea thrown in the wind, I'd be curious to know if you guys have considered it, and why not, etc.
     
  6. JoshPeterson

    JoshPeterson

    Unity Technologies

    Joined:
    Jul 21, 2014
    Posts:
    6,920
    The best description about why we went with IL2CPP is probably in this blog post, although I don't think that it addresses why we did not go with Mono ARM64 specifically:

    http://blogs.unity3d.com/2014/05/20/the-future-of-scripting-in-unity/

    The specific issues you raised are valid. Note that a 64-bit build of Mono would need to ship two copies of the binary as well, since iOS requires a native binary for each architecture and it does not allow code to be loaded dynamically at runtime. Once the metadata is completely externalized from the binary in IL2CPP, we expect the build sizes between the Mono scripting backend and the IL2CPP scripting backend to be comparable.

    We're actively on build time improvements now. We should have something available in the next patch release or two.
     
  7. PixelSquad

    PixelSquad

    Joined:
    Sep 4, 2014
    Posts:
    114
    Thanks for answering Josh. Is there someone from Unity who would be interested in having a look at our project to figure out why it has poorer performance with IL2CPP compared to mono?

    For us it's crucial to be able to maintain (or improve) performance on our next update, and it seems a lot poorer with IL2CPP

    And just commenting on your post above, priority wise, definitely performance and build size are the top priorities. Build time improvements is just something that'd be nice to have, but not essential. (Personally I could live with the current times if the other issues are solved.) Many thanks and all the best.
     

    Attached Files:

  8. JoshPeterson

    JoshPeterson

    Unity Technologies

    Joined:
    Jul 21, 2014
    Posts:
    6,920
    @PixelSquad

    Yes, if you can submit a bug report and provide us with your project, someone from my team will be happy to have a look at the performance difference. As I mentioned to @moonjump above, you may want to try 4.6.7p2 when it is out, as we have a few performance improvements in it. But we are always looking to profile performance issue.

    If your project is large, ping me separately we we can work out a way for us to obtain it. Thanks!
     
  9. dchau_hh

    dchau_hh

    Joined:
    Jan 22, 2014
    Posts:
    24
    @JoshPeterson

    Hi Josh,

    We've been using 4.6.6p1 since it was the first build that gave us a significant reduction in IL2CPP executable size and allowed us to submit our initial release of our game under the 100MB iOS limit. We're doing an update and getting right up against the limit again and I thought I'd try the most recent patch release to see if there might be some more gains.

    Unfortunately, these are the results...

    4.6.6p1

    Code Segment (armv7): 26755072
    Code Segment (arm64): 30343168
    Data Segment (armv7): 9945088
    Data Segment (arm64): 16023552

    Total executable size for App Store: (26755072 + 30343168) + (0.2 * (9945088 + 16023552)) = 62,291,968

    4.6.7p1
    Code Segment (armv7): 31703040
    Code Segment (arm64): 36618240
    Data Segment (armv7): 5046272
    Data Segment (arm64): 7585792

    Total executable size for App Store: (31703040 + 36618240) + (0.2 * (5046272 + 7585792)) = 70,847,693

    Does this fall within your expectations? The trade-off of data segment size for code segment size is a net loss for us since the code segment doesn't compress with Apple's encryption.

    Thanks for your active support here on the forums!
     
  10. JoshPeterson

    JoshPeterson

    Unity Technologies

    Joined:
    Jul 21, 2014
    Posts:
    6,920
    @dchau_hh

    Thanks for the reporting these numbers. I'll try to explain a bit about what is going to here, although we would prefer to see your project so that we can completely analyze it, if that is possible.

    This is not really a trade-off between the code and data segments, actually. We made the size of the data segment smaller between these two releases. We did increase the code size in some cases, mainly due to less generic sharing. Specifically, we stopped sharing a generic type with an Enum type argument with the same generic type and in int argument. In 4.6.6p1 we were doing this sharing, but it lead to some runtime bugs that required us to back off a little bit.

    After talking about this size increase a bit, we are surprised to see such a large increase from this one change. So, if we can have a look at your project here, we would love to do so.
     
  11. dchau_hh

    dchau_hh

    Joined:
    Jan 22, 2014
    Posts:
    24
    @JoshPeterson

    Hi Josh,

    I attached a slightly older version of our project to Issue 711871. It should produce a smaller executable due to having fewer static libraries from ad providers but should give similar results.

    Thanks!

     
  12. JoshPeterson

    JoshPeterson

    Unity Technologies

    Joined:
    Jul 21, 2014
    Posts:
    6,920
    @dchau_hh

    Ok, thanks for pointing this out. We will have a look at this project.
     
  13. PAHeartBeat

    PAHeartBeat

    Joined:
    Jul 11, 2012
    Posts:
    76
    Hi @catacomber,

    In one of our game we have tried it few weeks ago, and used only 64bit (ARM64) and droped ARMV7, it' was good to save build size in test localy. But at time of summision Apple store is not accept the Application / Game, whatever method we used to submit game (use APP, zip it and submit game via Application Loader or Archive project and submit from XCode)

    Right now I don't have screenshot for the message, may be we have few shots, but need to find. once I find it I will upload here for the referance
     
  14. Mantas-Puida

    Mantas-Puida

    Joined:
    Nov 13, 2008
    Posts:
    1,864
    During the last WWDC Apple announced that ARM64-only apps will be accepted into App Store. Not sure if they already rolled it out. Detailed rejection message would help.

    P.S. do you have ARM64 specified as a requirement in your info.plist under UIRequiredDeviceCapabilities?
     
  15. 5argon

    5argon

    Joined:
    Jun 10, 2013
    Posts:
    1,555
    Even though you said Stripping does not matter, I tried comparing no stripping and micro mscorlib and there is a 5MB different in size I got from TestFlight. Why is that so?
     
  16. JoshPeterson

    JoshPeterson

    Unity Technologies

    Joined:
    Jul 21, 2014
    Posts:
    6,920
    @5argon

    The fact that the Micro Mscorlib option is even in the stripping settings is a bit odd. Using the Micro Mscorlib doesn't really change the stripping behavior, but instead uses a smaller version of mscorlib.dll which has already had much of its managed code removed. So I would expect some size decrease (although 5 MB seems like a lot).
     
    5argon likes this.
  17. RoslukRoma

    RoslukRoma

    Joined:
    Mar 30, 2015
    Posts:
    3
  18. voldemarz

    voldemarz

    Joined:
    Sep 19, 2011
    Posts:
    25
    We're close to 100 MB limit and are trying to estimate app size as accurately as possible.

    The executable extracted from .ipa is 52.9 MB (52912640 B). Both "otool" and "size" report same 32/64 bit code segment sizes, but data segment sizes differ.

    "otool" data segment sizes:
    32 bit - 1769472 B
    64 bit - 2867200 B

    "size" data segment sizes:
    32 bit - 2588672 B
    64 bit - 3784704 B

    Why the difference?
     
  19. RoslukRoma

    RoslukRoma

    Joined:
    Mar 30, 2015
    Posts:
    3
    Decided, after assembly of the build you want to archive it means xCode, then the file code segment reduces its size.
     
  20. JoshPeterson

    JoshPeterson

    Unity Technologies

    Joined:
    Jul 21, 2014
    Posts:
    6,920
    @voldemarz

    I'm not an expert in usage of the otool and size tools, but I suspect that size is reporting greater values because it is less fine-grained than otool. The size tool is probably looking only at the data segment. The data segment is made up of multiple sections, and I suspect that otool is reporting the information for only one section of the data segment.
     
  21. 5argon

    5argon

    Joined:
    Jun 10, 2013
    Posts:
    1,555
    Now that my game is finally on the store, just for your information, my game is Universal (32,64 bit)
    Unity build log reports : 68.5 MB
    After upload to iTunes Connect and view the download size on Testflight : 94.8 MB
    When in the actual store 72.6 MB

    So what I wanted to say is don't freak out by the size that Testflight reports. It will reduce a bit more in the actual store.
     
  22. ababab5

    ababab5

    Joined:
    Apr 15, 2014
    Posts:
    508
    Hi,

    My game :

    On Android = 22.5MO

    iOS Universal (so .. IL2CPP) : 65MO

    How is it possible ?

    Thanks !
     
  23. JoshPeterson

    JoshPeterson

    Unity Technologies

    Joined:
    Jul 21, 2014
    Posts:
    6,920
    @ababab5

    This could occur for a number of reasons. The most likely cause is that the iOS universal binary includes both 32-bit and 64-bit executable slices. See the first post in this thread of a nice description about how to dig into the executable and better understand where the size is going.
     
    ababab5 likes this.
  24. ababab5

    ababab5

    Joined:
    Apr 15, 2014
    Posts:
    508
    Hi,

    I already read it.

    In my iOS IPA I have this files:
    • sharedassets1.assets : 11.3 Mo.
    • sharedassets1.resource : 3 Mo
    • "unity default resources" : 2 Mo
    • global-metadata.dat : 2 times the same file with exactly the same size = 3.6 Mo (one time in the root folder and the other time in Data/Managed/Metadata). It's the same, exactly the same.
    Do you have any idea to help us ?

    Thanks a lot!

    Best regards,

    AB
     
  25. JoshPeterson

    JoshPeterson

    Unity Technologies

    Joined:
    Jul 21, 2014
    Posts:
    6,920
    @ababab5

    The duplicate global-metadata.dat file sounds like a bug. I believe that is should only exist in the Data/Managed/Metadata directory. You can confirm this by manually deleting the copy in the root directory, and see if everything works. If so, please file a bug report.
     
  26. ababab5

    ababab5

    Joined:
    Apr 15, 2014
    Posts:
    508
    I'll do it when I will be back on my computer.

    Thanks for this, and I will (of course) let you know.

    But could you explain me please what's the other files ?

    Thanks a lot !
     
  27. JoshPeterson

    JoshPeterson

    Unity Technologies

    Joined:
    Jul 21, 2014
    Posts:
    6,920
    @ababab5

    I'm not too familiar with those files, but I do know that they are the packed assets used by your game. There is one set a sharedassets files per level you define. Note that these files should not differ at all for the IL2CPP and Mono scripting backends. Building for iOS with either scripting backend should result in the same files.
     
  28. ababab5

    ababab5

    Joined:
    Apr 15, 2014
    Posts:
    508

    Thanks again for your answer.

    That's the point : I only have one scene. And no sharedAsset
     
  29. JoshPeterson

    JoshPeterson

    Unity Technologies

    Joined:
    Jul 21, 2014
    Posts:
    6,920
    @ababab5

    Unfortunately, this is probably the wrong part of the forums to find an answer to that question. I know that I'm not the person to answer it, certainly! Maybe try asking about those files elsewhere on the forums?
     
    MrEsquire likes this.
  30. ababab5

    ababab5

    Joined:
    Apr 15, 2014
    Posts:
    508
    Ok thanks !
     
  31. rchapman

    rchapman

    Joined:
    Feb 13, 2014
    Posts:
    105
    "The IL2CPP scripting backend always does byte code stripping, no matter what the “Stripping Level” setting is in the editor."

    Why? What is the point of this setting if it makes no difference?

    This is an infuriating "feature" because it makes dealing with serialization agonizingly verbose and error prone. It's really, really annoying to try to keep a separate file up to date just to support deserializing objects. I would strongly request that we could actually disable stripping, or at least somehow make an exception for default constructors so that deserializers actually work.
     
  32. JoshPeterson

    JoshPeterson

    Unity Technologies

    Joined:
    Jul 21, 2014
    Posts:
    6,920
    @rchapman

    Yes, this is certainly confusing. We've improved the way it is displayed in the editor in the upcoming Unity 5.2 release to hopefully make it clearer.

    With the IL2CPP scripting backend, byte code stripping of managed assemblies is always enabled to help decrease the build size.

    The "Stripping Level" setting still exists because setting it to a value of "Disabled" prevents the native engine code from being removed. Setting "Stripping Level" setting to anything other than "Disabled" will cause some unused native engine code to be removed. So in 5.2, this option has become an on/off checkbox with the name "Strip Engine Code."

    More to your issue, it is possible to disable stripping for an entire assembly using a link.xml file. You can add the preserve attribute to an assembly element link this:

    <linker>
    <assembly fullname="MyAssembly" preserve="all">
    </linker>

    This will prevent MyAssembly.dll from being stripped at all. I hope that this makes things a bit easier to work with.
     
    larku and rchapman like this.
  33. rchapman

    rchapman

    Joined:
    Feb 13, 2014
    Posts:
    105
    Thanks Josh, I didn't realize you could opt-out a whole assembly. That does make life a lot easier. (Side note--any chance we could get this documented?) I also noticed that classes in the project itself aren't affected--could you verify that this is true?
     
  34. liortal

    liortal

    Joined:
    Oct 17, 2012
    Posts:
    3,562
  35. JoshPeterson

    JoshPeterson

    Unity Technologies

    Joined:
    Jul 21, 2014
    Posts:
    6,920
    @rchapman

    Yes, this should appear in the documentation soon. I modified our documentation code internally here when we implemented this new preserve attribute a few weeks ago. I'm not quite sure when it will make it to the online site though.

    When it appears, it will be here:

    http://docs.unity3d.com/Manual/iphone-playerSizeOptimization.html

    > I also noticed that classes in the project itself aren't affected--could you verify that this is true?

    Can you elaborate on this question? What do you mean by "classes in the project itself"? Thanks.
     
  36. CPXTom

    CPXTom

    Joined:
    Apr 24, 2010
    Posts:
    113
    @Iiortal the bug is still open and I can see from a latest build that they're still there.
     
    liortal likes this.
  37. liortal

    liortal

    Joined:
    Oct 17, 2012
    Posts:
    3,562
  38. dchau_hh

    dchau_hh

    Joined:
    Jan 22, 2014
    Posts:
    24
    @JoshPeterson

    Hi Josh,

    Did you ever get a chance to look at the large code size increase with our project? We've been trying the latest patch releases as they come out but the code segment delta remains around 10 MB and we don't have that space to spare under the 100MB Apple limit.

    What are your best suggestions for reducing code size? We use generics pretty extensively.

    Thanks!
     
  39. JoshPeterson

    JoshPeterson

    Unity Technologies

    Joined:
    Jul 21, 2014
    Posts:
    6,920
    @dchau_hh

    I apologize, this one has fallen through the cracks (entirely my fault). Thanks for pinging me again about it. I'll try to have a look at it in the next week and get back to you.
     
  40. JoshPeterson

    JoshPeterson

    Unity Technologies

    Joined:
    Jul 21, 2014
    Posts:
    6,920
    @dchau_hh

    I've finally taken a look at the project you submitted, sorry for the delay.

    Unfortunately, nothing jumps out at me as a cause for the increase in size. As I mentioned above, the smaller data segment size is not a trade-off with the code segment size, but is likely unrelated.

    I did look a the linker map file to get a sense of the possible cost of the change to not share generic enum types. I see about 3,600 entires for List<T> which are not shared, and about 3,600 entries for Dictionary<T> which are not shared. The average size for these entries is about 32 bytes, so it seems like they add about 120 KB each.

    So, it seems that you would need to have about 40 different generic types that use enums to account for the about 5 MB difference in the size of the armv7 code segment between versions. That seems like a large number to me, but if the code has something on that order, then the change in size can likely be attributed to our change in enum sharing.

    Does this sound like it might be the cause? If not, then we may need to dig in further.
     
  41. JoshPeterson

    JoshPeterson

    Unity Technologies

    Joined:
    Jul 21, 2014
    Posts:
    6,920
    @dchau_hh

    Unfortunately, I need rescind most of what I said above. I was doing a similar analysis of a project for another user yesterday as well, and that user pointed out an important flaw in my analysis process. I was missing a significant part of the code which occurs because IL2CPP does not share generic type implementations with enums.

    In the project that user was working on, a change to use int types instead of enum types in generics reduced the binary size of the output executable by about 10%. So it is not unreasonable to say that the increase in size you saw between the two versions of Unity was indeed due to our change to not share generic types with enums.

    If you are looking to decrease the size, it may be beneficial to try replacing some generic types in the project which use enums with generic types that use int, so the implementation of those generic types can be shared.

    Sorry about my initial, incorrect analysis. Hopefully this clears things up a bit.
     
  42. dchau_hh

    dchau_hh

    Joined:
    Jan 22, 2014
    Posts:
    24
    @JoshPeterson

    Thanks for the update Josh! We could start migrating our enums to ints (or possibly strings since there are many that are just keys in collections). Hopefully that would maintain our current code size with a more up to date version of the IL2CPP generation. Do you have any other suggestions for further reducing code size? Our executable continues to grow as we add features in updates and we're running out of assets that can be squeeze or removed from our package.
     
  43. JoshPeterson

    JoshPeterson

    Unity Technologies

    Joined:
    Jul 21, 2014
    Posts:
    6,920
    @dchau_hh

    Unfortunately no, I don't have any other suggestions for build size reduction now. App thinning for iOS9 is likely the next big helper. We've shipped support for that in 5.2.1p1, but Apple has turned it off for now. Once they sort things out and enable it again, I would definitely take advantage of that.
     
  44. dchau_hh

    dchau_hh

    Joined:
    Jan 22, 2014
    Posts:
    24
  45. JoshPeterson

    JoshPeterson

    Unity Technologies

    Joined:
    Jul 21, 2014
    Posts:
    6,920
    @dchau_hh

    Yeah, unfortunately requiring iOS 9 is not a real possibility now.

    That optimization has not made it into any release from us yet though. I've heard of a few others using it via a third-party tool like the one described in that thread or a custom tool though.
     
  46. jesusluvsyooh

    jesusluvsyooh

    Joined:
    Jan 10, 2012
    Posts:
    377
    Released my App last month, was 98mb (says on app store) the one i released a few days ago to fix a chat bug, with no other changes, now shows it as 120mb on app store XD
    Thats one huge difference, i believe i updated Unity from
    4.6.8p2 to 4.6.8p3 and xCode from 6 something to 7.

    Already compressed sounds and textures to hell to get it to that original 98mb that it was, hope Apple increase their wifi download size from 100mb soon, seem to be getting slightly less downloads now >_<

    Will check my old iPhone 4 and see if the app store size is different to what the iphone 6 store size shows.
    Edit : iPhone 4 app store page shows it as being 86mb. Interesting :eek:
     
    larku and MrEsquire like this.
  47. JoshPeterson

    JoshPeterson

    Unity Technologies

    Joined:
    Jul 21, 2014
    Posts:
    6,920
    @jesusluvsyooh

    I'm surprised to see such a jump in size between 4.6.8p2 and 4.6.8p3. But maybe it comes down the to way Apple is reporting it, I'm not sure.
     
  48. larku

    larku

    Joined:
    Mar 14, 2013
    Posts:
    1,422
    I can confirm that going from 4.6.8p1 to 4.6.8p3 increases our submitted binary (as reported by Apple in the 'Build Details') from 77.1MB to 106MB.

    Identical project built with same XCode, but different unity version.

    4.6.8p1 = 77.1mb
    4.6.8p3 = 106mb

    Certainly something going on there.

    I think I'll have to submit a build built with 4.7.8p1 ..
     
    jesusluvsyooh likes this.
  49. jesusluvsyooh

    jesusluvsyooh

    Joined:
    Jan 10, 2012
    Posts:
    377
    @larku @JoshPeterson Similar to my situation, i think it may have been 4.6.8p1 - 4.6.8p3 for me too then, thinking back about it and looking at the release dates of the game and Unity patches
     
  50. JoshPeterson

    JoshPeterson

    Unity Technologies

    Joined:
    Jul 21, 2014
    Posts:
    6,920
    @jesusluvsyooh @larku

    I'm a bit surprised, as it doesn't look like we did too much on the IL2CPP side to increase build size between those releases. I do see this entry in the release notes:

    iOS/IL2CPP: Ensure PreserveAttribute on type preserves default constructor

    This change means that if you use the [Preserve] attribute on a type then we will no longer strip the default constructor for that type. I doubt that could increase the project size so significantly. Can one or both of you provide a project in a bug report? I would like to have a look at the project build in both versions to see if we can do something.