Search Unity

Profiler is unusable for both iOS and Android

Discussion in 'Editor & General Support' started by novaVision, Dec 28, 2020.

  1. novaVision

    novaVision

    Joined:
    Nov 9, 2014
    Posts:
    518
    First of all make sense to mention that Profiler worked months ago when I used 2019.3. After I migrated to 2020.1 about a week ago I tried to profile the app but that was absolutely impossible.
    1. on iOS after attaching the profiler app FPS drops to 1-5, and after 5-10 seconds the app freezes. XCode throws the exception "BAD_ACCESS". It also says:
      Code (CSharp):
      1. UnityFramework was compiled with optimization - stepping may behave oddly; variables may not be available
      If XCode debugger is not running and only Unity Editor attached to the app, it just crashed after 5-10 seconds.
    2. on Android happens the same scenario. LogCat spamming allocation messages.
    The only way I found I can somehow profile the app is to use Memory Profiler making snapshots. That' all - no other way to get CPU profiling data.

    Note - it's just UI based application, no heavy elements like 3D assets and huge textures.
    How to solve it? Is it a Profiler bug?
     
  2. MartinTilo

    MartinTilo

    Unity Technologies

    Joined:
    Aug 16, 2017
    Posts:
    2,455
    As noted in the other thread: yes this is a bug. The Profiler isn't supposed to crash neither the Editor nor the player. If it does, please report a bug, ideally with a crash report attached. That way we can investigate it, pinpoint it match it up with other reports (via crashlog similarities) which can help isolate the issue, and get some Critical hardware stats that we don't get in forum threads.
     
  3. novaVision

    novaVision

    Joined:
    Nov 9, 2014
    Posts:
    518
    Attached project settings and logs to the bug report (Case 1302353)
     
    Last edited: Dec 29, 2020
  4. MartinTilo

    MartinTilo

    Unity Technologies

    Joined:
    Aug 16, 2017
    Posts:
    2,455
    I think we might need a project to reproduce this. Looks like you are triggering the GC multiple times per second which might contribute towards the crash. Disclaimer: I'm on vacation and only had a cursory look at the logs from my phone.

    Btw you might want to change your post to only show the issue ID instead of your private link with which everyone can see the other issues you reported.
     
  5. MartinTilo

    MartinTilo

    Unity Technologies

    Joined:
    Aug 16, 2017
    Posts:
    2,455
    So judging by the logs there's so much managed memory being allocated that the GC can free ~400KB 4-6 times per second.
    Also UserStatsScreen StatsDataLoaded looks like it is trying to deserialize from JSON via newtonsofts JSON tool a type with a generic list on it, triggering generic methods (ThrowHelper_IfNullAndNullsAreIllegalThenThrow_TisRuntimeObject) and while that method is made concrete, it's being registered with he profiler and that's where it crashes.

    So really, while we might try to blind fix something, a project would be very good to help us address this because it seems rather unusual scenario with quite the load on the memory and profiler system. Maybe zip one up already to keep a copy of he current state.
     
  6. novaVision

    novaVision

    Joined:
    Nov 9, 2014
    Posts:
    518
    I can't provide the project.

    Is there any way to check on my end, what exactly can trigger CG so often?
     
  7. MartinTilo

    MartinTilo

    Unity Technologies

    Joined:
    Aug 16, 2017
    Posts:
    2,455
    Well it's very likely a fault with the Profiler code. but It could be FireBase, GameAnalytics or something else triggering the JSON deserialize, an operation which under most JSON solutions is rather allocation happy due to string usage. In this case it seems to be triggered by a webrequest iirc. That GC hammering + incremental GC plus generics is likely a combination that is creating an unusual situation for the profiler code. May I ask why you can't share the project? This seems very worthwhile for us to fix
     
  8. MartinTilo

    MartinTilo

    Unity Technologies

    Joined:
    Aug 16, 2017
    Posts:
    2,455
    The Profiler can tell you what is allocating so much. Look out for GC.Alloc samples, which are bright magenta in the CPU timeline view, and in Hierarchy you can search for them. The Allocation Callstacks feature can help pinpoint the allocations without need for deep profiling. Not sure what of that would only happen on a device but likely it's also allocating quite a bit in the editor.
     
  9. novaVision

    novaVision

    Joined:
    Nov 9, 2014
    Posts:
    518
    The only way I could run Profiler on the device is simple (not deep) option. From what I see there it relates to scrollable list (OptimizedScrollAdapter asset), where each new item loads small texture on become visible. it's about 100kb only
    Also there are a lot of small GC.Alloc (30-60b) probably cause by SoftMask component:
    4.png

    These screenshots represents WebRequest where pretty much string forming used to provide request details.
    1.png 2.png

    Anyway, doesn't looks something critical, at least before I used same texture loadout logic and didn't get crashed profiling it. Furthermore, deep profiling iOS build before it crashes (I still have some 5 seconds) the was only 0.5kb allocation, but instead there is huge CPU spike (160ms) in EarlyUpdate.PollPlayerConnection > PlayerConnection.Poll
    We discussed the case with product owner, and we can share the project for investigation
     

    Attached Files:

    • 3.png
      3.png
      File size:
      139.8 KB
      Views:
      290
    Last edited: Dec 29, 2020
    MartinTilo likes this.
  10. MartinTilo

    MartinTilo

    Unity Technologies

    Joined:
    Aug 16, 2017
    Posts:
    2,455
    That's good to hear. Would be good if you could zip it up to conserve the current state until QA gets in touch to provide you can upload link. Or you could create a new bug report, attach he project there and I'll join the two reports as duplicates.

    Have you tried turning the incremental GC off and profiling then? Could be a way to isolate the issue and provide you with a workaround until we have a fix (provided it does help). Though having incremental GC on also generally lowers scripting performance through the board, so that'd change performance a bit besides garbage collection times.

    Also, if those alloctions are one off, e.g. per scene/screen switch, then it might be fine. If they are per frame or very regular, you might still want to look into ways to reduce them somewhat through caching, pooling and recycling. Also, the link I provided above about Allocation Callstacks contains instructions on how to get more details on all these allocations to take out the guesswork of where they originated exactly in the code and with one hints as to why (based on the mono internal calls in the call stack).

    I guess your app is likely not CPU bound but if you have memory issues, it might be good to have a look at these allocations, if the memory issue is in managed (Mono/IL2CPP) memory.

    Btw, are you using the Memory Profiler package to hunt down your memory issues? The memory map in the package might show if these usage patterns here leads to managed memory fragmentation, it'd show that, even if the UX for that could and will be greatly improved as we build this tool out further.
     
  11. novaVision

    novaVision

    Joined:
    Nov 9, 2014
    Posts:
    518
    Done. New case: 1303033

    We got a lot of dynamically loaded (from Web or Locally stored) images used in a scrollable content. Probably, I overplayed with a RAM optimization trying to unload the graphics assets each time on item being disposed (returned to the pool) to avoid keeping unused assets in the memory. I assume in this case would be better to keep them all cached.

    Also SoftMask asset looks suspicious. Each UI item in scroll content has up to 4 soft masks and seems each of the mask allocates ~30b of memory. Can't say, is it fine or not, but maybe make sense to reduce it only to where it's actually needed, not all the maskable images.

    Yes, I used for graphic assets optimization, but I have no idea how can it help in my case - it doesn't capture the memory map each frame but only by triggering capture in editor. How can I do it exactly in the frame when that GC heaps appears? Also, the list of elements is huge... I don't understand how to sort out only what I need
     
    Last edited: Jan 2, 2021
  12. MartinTilo

    MartinTilo

    Unity Technologies

    Joined:
    Aug 16, 2017
    Posts:
    2,455
    Thank you, marked as duplicate to link them :)

    So you are destroying the Texture2D and periodically call Resources.UnloadUnusedAssets? Because without that call, only GC.Collect would every now and then get rid of the managed shell objects but retain the native memory until the next non-async/destructive scene unload or asset unload.