Search Unity

  1. Welcome to the Unity Forums! Please take the time to read our Code of Conduct to familiarize yourself with the forum rules and how to post constructively.
  2. Dismiss Notice

waitfortargetfps high cpu usage

Discussion in '2D' started by hgokturk, Jul 13, 2018.

  1. hgokturk

    hgokturk

    Joined:
    Jun 29, 2016
    Posts:
    17
    Hey,
    Although the vsync is disabled in the quality settings, waitfortargetfps consumes 80% of cpu. Testing with samsung tablet. What is causing it?
     
  2. MartinTilo

    MartinTilo

    Unity Technologies

    Joined:
    Aug 16, 2017
    Posts:
    2,160
    What's your actual frame rate (mobile devices are throttled to 60 fps (if you've set Application.targetFPS = 0 otherwise it's 30 iirc) but 80% waiting sounds like an empty scene)?
    What is your project, Unity version number, details on the tablet?
    And could you save out your profiling data (maybe zip it) and upload it?

    you could also try deep profiling when you compile as a mono build and start through
    adb shell am start -n com.company.game/com.unity3d.player.UnityPlayerActivity -e 'unity' '-deepprofiling'

    Also see https://unity3d.com/learn/tutorials/topics/best-practices/unity-profiler
     
  3. hgokturk

    hgokturk

    Joined:
    Jun 29, 2016
    Posts:
    17
    Hey. I force 60fps but get around 40. Attaching profile data and screenshots of settings. Really stuck here. When i turn vsync on, it goes very well for about 5 minutes then fps drops to 30's again.
     

    Attached Files:

  4. MartinTilo

    MartinTilo

    Unity Technologies

    Joined:
    Aug 16, 2017
    Posts:
    2,160
    We sadly don't (yet) save the version the profiler data was generated with and it is not compatible across versions. I did manage to open it with 2017.4f5 but it would still be nice to know which version you're using.

    In the profiler data you attached, WaitForTargetFPS maxes out at 12.2% in frame 19 and is otherwise nearly non existing. You do however have a regular Device.Present in there at ~12%. Compared with WaitForTargetFPS, that happens at the beginning of your frame instead of at the end and is waiting for the refresh rate of your screen and might get bogged down by rendering? I'm not an expert in this area but I guess anything you can do to remove load on Rendering will help you.
    Especially, because it does show you're somewhat below 60 FPS and spending a ton of time in Camera.Render rendering transparent geometry. Transparency on mobile devices is known to be slowish. Are you using cutout shaders? A lot of overdraw? Try Using Multithreaded Rendering, enabled in the "Other Settings" of your build settings.
    Also see:
    https://forum.unity.com/threads/unity-profiler-device-present-and-fps-drop-problems.501195/
    https://forum.unity.com/threads/device-present-in-profiler-what-the-deal.86312/
    https://forum.unity.com/threads/wha...profiler-and-why-does-it-take-so-long.478274/

    Further, that FPSDisplay you're using (I guess the first one from the wiki) is using IMGUI and allocating 2.1KB each frame. Maybe look into GC.Alloc free StringBuilder implementations like this one (that I haven't tested, just found on google) or similar to output text that frequently changes.

    Since you're already using UGUI, maybe try using this one and hook it into UGUI. Give it it's own canvas so the constantly updating text doesn't dirty the layout for your entire UI.
    Speaking of your UI: Seems like there's probably something else in there that constantly changes and dirties the layout so it needs to be rebuild, as you're spending quite some time in that too. maybe checkout this talk


    You're Swipe manager also allocates 2.7KB occasionally and probably doesn't have to. I'm guessing it creates class instances to trace the input when it could use structs? Interestingly, you're GC.Collect doesn't take too much time at ~2ms but when you're flush against your target fps, any bumb like that will become noticable. There's quiet some (even high profile) mobile games out there that share that very distinguishable GC.Collect hickup in regular intervals. So 1. it's a common problem and it's not trivial to keep your GC.Allocs during gameplay down but 2. it's a nice added polish if you're frame time can be a bit more consistent and GC.Alloc in itself already takes up some time, not just GC.Collect.

    Also, from experience, if you're using swipe input and have spikes while swiping, that means your input might not be read correctly since Input is querried on a per frame basis. You're drops in this don't seem too bad yet but on lower-end devices, this might make for clunky controls.

    I've attached a screenshot from the CPU Profiler's timeline view highlighting your biggest problem areas.
    Left to right they are
    1. Device.Present
    ->Maybe due to too much todo for the GPU, like culling and overdraw? Not sure about this myself
    2. UGUI Layout
    ->Cut your canvas apart, one for static things, one or more for elements that update frequently
    3. Render.TransparentGeometry
    ->See if you can't reduce the load on transparent geometry.
    4. UIEvents.IMGUIRenderOverlays
    ->port the FPS counter over to UGUI and reduce the amount of GC.Alloc in there and in Swipe

    Lastly, your frame drop after a while is probably the device getting too hot. Updating a tablet screen at 60fps will heat up the device, the more you reduce the time spend on the CPU, the less hot the CPU will get because it can idle more, but at some point, the heat will cause the OS to throttle the device and that's the drop you're likely noticing.
     

    Attached Files:

    angrypenguin and chelnok like this.
  5. hgokturk

    hgokturk

    Joined:
    Jun 29, 2016
    Posts:
    17
    Hey, thank you very much for your extended help. My version of Unity is 2017.4.7f1.
    If i stop enforcing fps then rotation of 1 sprite object becomes laggy. Can Render.TransparentGeometry problem be caused of using sprites with transparent content? I use 1080x1920 design of sprites for my game. Speaking of canvas, there is only 1 text which is changed at runtime. I don't think it can cause lag.
     
  6. MartinTilo

    MartinTilo

    Unity Technologies

    Joined:
    Aug 16, 2017
    Posts:
    2,160
    Ok, that means I was looking at your profiler data with the right version. In that case, the topic of this thread is probably a bit misleading as, at least from the profiler data you attached, nothing you described in your first post actually shows up containing any significant occurrences of WaitForTargetFPS. Maybe it does once the device is overheated?

    Yes. Actually all sprites could show up as transparent because the default sprite shader is (I think) using the transparent render queue. Not sure if you could just swap their shader for one which is opaque when they are not using transparency

    Do you mean, that 1080x1920 is the target resolution for which you design your sprites and that you base your pixel density based on that? Then I'm not sure how that is relevant to your performance problems other than that it is a reasonable scale to aim for (when the tablet is your aim) and the resulting textures are probably a normal use case.

    However, that does not mean that your configuration is ideal. You could investigate into how your sprites end up in atlases and get packed, maybe split them and organize them differently in the atlases (using the packing tags). Maybe the atlases end up too big, or too fragmented. All those texture uploads to the GPU take their time so this has all sorts of implications. I'm however not the right person to help you with that but there's probably some (Unite) talks or forum threads about performance optimizations, especially regarding sprites that might help you with this.

    Yes it can. String manipulation in c# is costly and allocates a bunch of stuff on the heap as all strings are immutable heap objects. The profiler showed it as 2.1KB GC.Alloc every frame for your case. As I said, that's a bit of time cost on Allocation, and then a bigger chunk of time for GC.Collect, which is a 2-3ms spike you're regularly getting according to your Profiling data. Being this flush against/over your target fps, these spikes can be enough to be noticeable hiccups.

    Additionally, as you can see in the screenshot, the entire FPSDisplay.cs thing causes IMGUI to be active and waste another 2ms of your frame time. (A good chunk of that time is spend on those pink GC.Alloc calls too)

    If you have to stick to 60 FPS for your game to feel smooth, you'll have to double down on reducing the CPU and GPU load and try to leave idle time for both so they have some cool down time, but at the end of day, different mobile devices all potentially have their own heat thresholds at which they will slow down. There are some hacks to deal with that but non that I'm firm with, but there might be something googleable. Also, keeping that pace up means you're draining your battery pretty fast.

    All in all, the heat/throttling is however something neither you nor we have a direct control over and in a market space as fragmented as Android, there will always be devices where you're game will pass the heat threshold or generally perform bad on. So you'll need to figure out, what the minimum specs are, test on some minimum spec devices and try to keep your performance in reasonable levels. You can maybe also try to do resolution scaling or dropping your target FPS while in menu or when your FPS drop so the device can cool down again.

    Also, another resource you might want to dig through is our Best Practices guides:
    https://unity3d.com/learn/tutorials/s/best-practices
     
    angrypenguin likes this.
  7. hgokturk

    hgokturk

    Joined:
    Jun 29, 2016
    Posts:
    17
    I confirm that the problem is caused by the Admob banner ad unit in the scene.