Search Unity

Mono vs IL2CPP

Discussion in 'Editor & General Support' started by KyuVulpes, May 28, 2018.

  1. KyuVulpes

    KyuVulpes

    Joined:
    Nov 9, 2016
    Posts:
    38
    So I've been noticing that IL2CPP has been showing up more and more and Mono showing up less and less. And from research that I'm doing, it seems that IL2CPP seems to be better but compile times are slow. So, is it better to use IL2CPP over Mono, and why? Also, why is IL2CPP becoming so pronounced over Mono? Another thing, don't know where to put these questions so I'm putting them here.
     
    josetteseitz likes this.
  2. JoshPeterson

    JoshPeterson

    Unity Technologies

    Joined:
    Jul 21, 2014
    Posts:
    6,936
    There are a number of trade-offs in both directions. The two scripting backends are different - your choice depends on your use case. Here is a far-to-brief overview:

    Ahead-of-time (IL2CPP) vs. JIT (Mono) compilation:

    Compile times for AOT are longer, but the binary is completely specified when you ship a game. JIT compilation is faster, but compilation to machine code occurs on the end user's device (many platforms are AOT-only, so you may not have a choice). JIT is more flexible - you can use more of .NET, where AOT is faster for some cases (e.g. IL2CPP is better at floating point math than Mono).
     
  3. Mazak

    Mazak

    Joined:
    Mar 24, 2013
    Posts:
    226
    Can we expand on this difference?

    IL2CPP has been in works for several years.

    What about libraries?

    I use several external libraries how are these .NET libraries effected?
     
  4. Peter77

    Peter77

    QA Jesus

    Joined:
    Jun 12, 2013
    Posts:
    6,618
    sj631, PutridEx and OneSketchyGuy like this.
  5. JoshPeterson

    JoshPeterson

    Unity Technologies

    Joined:
    Jul 21, 2014
    Posts:
    6,936
    IL2CPP should work fine with any library that works with an AOT platform. If if the library uses dynamic code generation (via System.Reflection.Emit), it won't work with IL2CPP.

    In general, IL2CPP correctly converts and runs any .NET code from C# (we don't support F#, for example) - modulo bugs, of course (but we try to fix those pretty fast).
     
  6. Waz

    Waz

    Joined:
    May 1, 2010
    Posts:
    287
    I've tried IL2CPP a couple of times but always run into unimplemented functions. For example,

    IL2CPP does not support FileSystemWatcher for some reason.

    IL2CPP does not support marshaling delegates that point to instance methods to native code, so Facepunch.Steamworks doesn't work with it.

    So while YMMV, I measured it more in yards than miles.
     
  7. FlightOfOne

    FlightOfOne

    Joined:
    Aug 1, 2014
    Posts:
    668
    I am programmer in learning :), so not too experienced with what goes on in the back end...

    In simple terms, as of 2018.2.x can I set my project (building for windows 10) .Net 4.6 and IL2CPP and move on? In other words is there a reason NOT to use 4.6/IL2CPP?

    Thanks!
     
    Last edited: Jan 14, 2019
  8. hippocoder

    hippocoder

    Digital Ape

    Joined:
    Apr 11, 2010
    Posts:
    29,723
    There is no reason to avoid using IL2CPP unless you're doing some weird runtime wizard nonsense (reflection) or you need to have faster build testing cycles and your code changes a lot

    Further details:
    https://docs.unity3d.com/Manual/IL2CPP.html
     
  9. Thre3ouls

    Thre3ouls

    Joined:
    Apr 13, 2016
    Posts:
    22

    The reason is that IL2CPP does not support marshaling delegates that point to instance methods to native code, so Facepunch.Steamworks doesn't work with it.

    So if you have a fix for this please let us know.
     
    daisySa likes this.
  10. hassonhamo3

    hassonhamo3

    Joined:
    May 25, 2018
    Posts:
    38
    i'm publishing my game to android platform , which one should I go for ? I've tried both and didn't see any difference :)
     
  11. hippocoder

    hippocoder

    Digital Ape

    Joined:
    Apr 11, 2010
    Posts:
    29,723
    IL2CPP is always faster, so it will likely assist on slower devices. For further performance I would recommend gpu optimisations.
     
    IgorAherne likes this.
  12. Baste

    Baste

    Joined:
    Jan 24, 2013
    Posts:
    6,338
    IL2CPP seems to extend the time it takes to build by.... a lot. I don't think it can be understated just how much slower IL2CPP is than Mono. Which makes sense - cpp is a lot slower to compile than C#, and you also have the whole conversion step in there.

    My experience has been that it's not viable to use IL2CPP to produce builds for testing without a build server. It's also deeply problematic for profiling - you should profile builds, but when builds takes 30 minutes to and hour (or longer), checking if a single change makes a difference for runtime speed becomes a several hour project.

    The manual says:
    "Tip: You should use IL2CPP to both develop and ship your Project. If iteration times end up being too slow using IL2CPP, switch temporarily to the Mono Scripting Backend during development to improve iteration speed."

    I think that "if" could safely be changed to "when".
     
  13. charlie_sbg

    charlie_sbg

    Joined:
    Dec 18, 2016
    Posts:
    13
    The elephant in this room seems to be build size. I went up 12.7 MB! I'm still looking into this, if some engine stripping works I can possibly drop that to an expansion of 7.9 MB. That's still sizable. This is a typical free-to-play mobile game with puzzle and meta game.

    The trade-off is supposed to be that it loads and runs faster. But my iOS experience (which has been il2cpp for years) is, eh, not so much.

    So I can't complain because Unity is a great tool. But it's hard to polish the cost here. Hopefully it pays off somehow.
     
  14. wuhaiquan

    wuhaiquan

    Joined:
    Aug 30, 2019
    Posts:
    1
    every platform(armebi-v7a/arm64/x86) will generate a libil2cpp.so, have any suggestion to handle it?
     
  15. BlackManta

    BlackManta

    Joined:
    Nov 21, 2014
    Posts:
    7
    IL2CPP does not support C# processes! If you are designing a server for Linux you cannot use IL2CPP.
    I am shocked they have fixed this yet.

    ***
    In theory I would choose IL2CPP as its performance should be better. I am just at a show-stopper now that I can't spawn a new process with C#
     
    Haxel0rd likes this.
  16. cperera

    cperera

    Joined:
    Feb 29, 2020
    Posts:
    1
    My big question is - how much overhead is it to develop (just a single project) using Mono, then switch the project to IL2CPP? The usual obvious answer being, 'It depends on what you are up to'... but does anyone else have any experience here?
     
    AldeRoberge likes this.
  17. FlightOfOne

    FlightOfOne

    Joined:
    Aug 1, 2014
    Posts:
    668
    I do not have (doubt anyone would, but feel free to test yourself) one to one comparison since there is no reason to have two identical projects with mono and il2cpp.

    That being said, I do have a project (around 80 gb project and around 3gb built) and I did not notice any slowness that is worth mentioning or made me wonder while developing. I think where you pay little bit of time is when you build. Mono little faster. However you would only notice (from my experience) when you do your initial build. You probably won't notice much difference for incremental builds, unless your project is large, like over 10-15 gb after build. Honestly, you should have a separate build machine. Just let it do its thing while you work.

    I personally would not base my decision on development overhead though, I would gladly pay that price for runtime performance.

    Ultimately test it out with your prototype on your target device. For the most part (assuming you do not use any assets with limitations or your target platform) you can switch between the two.

    Be aware of other nuances though, things like modding (make is difficult with il2cpp)
     
  18. madkevop7

    madkevop7

    Joined:
    Nov 11, 2021
    Posts:
    23
    is modding easier with mono?
     
  19. iagofg

    iagofg

    Joined:
    May 23, 2013
    Posts:
    5
    We were developing a game and with Mono backend performance was more than acceptable, however no ARM64 support is available... when we switch to IL2CPP we discover horrirized that the performance was clunky and slow... WHEN RUNNING (compile time were also 4x o 8x longer). We tried with the latest Unity and same history... how is this possible? Please add ARM64 mono backend support!!!
     
  20. Tautvydas-Zilys

    Tautvydas-Zilys

    Unity Technologies

    Joined:
    Jul 25, 2013
    Posts:
    10,680
    Either you're building in debug configuration (check your player settings) or you hit some pathological case (in which case a bug report might be needed).
     
  21. iagofg

    iagofg

    Joined:
    May 23, 2013
    Posts:
    5
    Both places marked for release: in player settings where IL2CPP is chose and in build dialog... after reading several issues adding some conditional removal for some try..catch blocks fixed a bit the clunckiness... but code can be now far more unstable because failing in an operation can now break everything or at least all the frame process... and however... is still slower.

    Also for some reason now the default fps is now 30 instead of 60fps (and is settings issue because game has several fps settings and if I use a no-vsync with targetfps as 60, then the game reaches the 60fps, still there are frame count drops... but keeps running at 60fps while not heavy processing occur... the most incredible is that running on 64 bits should be faster, but it isn't...
     
  22. darkAbacus247

    darkAbacus247

    Joined:
    Sep 7, 2010
    Posts:
    251
    Hey all :)
    Sorry to bomb this post but this feels like the best place...

    Anywho, I've recently moved into unit 2021.3.11f1, HDRP to attempt to take advantage of updates via unity and external assets, yada-yada.

    Long story short, I've created a side project, copied all settings from main project and imported 3rd party assets. Everything good to go, no errors no issues...

    - BUT -

    EXE immediately crashes on launch, no bug reports just dies soon as UNITY logo fades out. Assuming it was an asset I restarted this entire process to find that if I simply create a new project, install ONLY entities to the project and switch over to IL2CPP I can no longer build. These are the ONLY steps that need to be taken to replicate this error.

    With that being said I researched a bit and found myself down a rabbit hole that took me to - publish-builds-in-unity-ecs. I was able to replicate the guides setup and build again...though of course I now have a load of other issues I'm entirely unfamiliar with - I can build with the original project settings though. Just nothing seems to work as expected, streaming scenes don't load anymore, this thing is broken that thing is broken but at least there aren't errors.

    Anyway I'm ranting at this point, hopefully someone could point me in a direction?

    Thanks all!
     
    MarsLars likes this.
  23. NoTuxNoBux

    NoTuxNoBux

    Joined:
    Oct 2, 2020
    Posts:
    34
    It might also be worth mentioning that AOT (what IL2CPP does) is not necessarily faster than JIT (what Mono does), though it might. As mentioned above AOT ensures everything is "known" up front (it's a fully native binary), and there is no compilation step left on the target device, which sounds positive as you shift that partial compilation step to the development instead of every user device.

    The other side of this double-edged sword is that in practice, with AOT, most developers produce a single binary or executable for a target platform, which means they target the lowest common denominator of feature sets of the target architecture as they want as many people to be able to run as possible. A good example of this is x86-64, where modern CPUs support more features (e.g. AVX-512) than older ones, but these native builds don't take advantage of them because doing so would break the binary for older processors. This is where JIT can shine (I can't say for sure if Mono or .NET do so, though), as it can compile and optimize on the target device for the target device, taking all supported features into account.

    I also vaguely recall the existence of JIT engines that recompile on-the-fly as code executes as they notice where hot paths lie, further optimizing them, so the application gets faster as it runs.

    (In practice it's even more complicated since C libraries such as glibc might have special dispatching functions based on the platform and might make a more informed decision at runtime, whilst still being AOT.)

    With AOT you could theoretically create binaries for several generations of, or even every model of, CPUs within the target architecture, but that is rarely done in practice. For example, GCC supports x86-64 microarchitecture levels to establish some common baseline between generations of processors, which will allow using more of the features your specific processor supports - but using all of them fully can still mean making an AOT build specific to your processor.

    tl;dr: Always evaluate your specific scenario and tailor towards what you need. AOT might not be a magic bullet yielding free performance.
     
    Haxel0rd and Starpaq2 like this.
  24. OctoSharko

    OctoSharko

    Joined:
    Dec 9, 2016
    Posts:
    36
    baermbtl likes this.
  25. baermbtl

    baermbtl

    Joined:
    Jun 29, 2023
    Posts:
    1
    I've the same problem as OctoSharko... The incompatibility warning for Android 14 when using Mono. And I can not change to Il2Cpp since my codebase is full of "weird runtime wizard nonsense (reflection)" - hippocoder.

    So If anyone has another solution I would be happy to have an reply