Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

iOS background thread slow down when UI is idle

A bit of context first

I have a Xamarin app that essentially streams video from a remote server. I have a background thread that loops like this (pseudo-code):

private void UpdateMethod()
{
    while (running)
    {
        bool success = WaitForUpdate();

        if (!success)
        {
            break;
        }

        Update update = GetUpdate();
        SendUpdateToConcurentQueue(update);
    }

    Disconnect();
}

I start the background thread like this:

Thread thread = new Thread(UpdateMethod);
thread.IsBackground = true;
thread.Start();

The issue

When I start the stream, everything is perfect. It's only after ~10 seconds of not interacting with the device that it becomes really slow. I've outputted the number of updates from the background thread, and they seem to come in a lot slower. I usually get around 2-6 updates to process per update (60fps). When it's super slow, I get 1 ever 6 update cycle.

One thing that puzzles me: When I pull down the iOS top bar menu, the updates go back up and the stream is suddenly back to normal speed. Update rate goes up for ~10 seconds and it goes back to lagging like crazy.

What I've tried

I tried to start a Dispatch queue with only this in it, like this:

DispatchQueue queue = new DispatchQueue("updateQueue");
queue.DispatchAsync(this.UpdateProcess);

It didn't seem to help at all.

I also tried to change the QualityOfService property in my update thread like this:

NSThread.Current.QualityOfService = NSQualityOfService.UserInitiated

Doesn't work either! It seems to me that iOS lowers my thread's priority for some reason. If I put a breakpoint in my UpdateMethod method, it's being hit when the app doesn't lag. But when there's lag, the breakpoint doesn't get hit. Now this really puzzles me, since the code still runs! I still receive the updates, it's just way slower...

Edit: I tested using Instruments and found that the network is being throttled... Investigating, but if anyone has knowledge of any kind of network throttle on iOS, let me know.

like image 533
Philippe Paré Avatar asked May 05 '16 18:05

Philippe Paré


1 Answers

Try setting the IdleTimerDisabled to true, we do this all the time in iOS games to keep iOS from idling our games.

Note: We do this in a polite way only when the user is not touching the screen due to watching a replay, level changing multimedia segues, etc...

Note: Make sure that you do reset the idle when you do not need it (when you app does go in the background, etc...), as from killing battery and making users bummed out about your app to the real killer: Apple Store rejections

Apple: App Idle Timer info

Xamarin: UIKit.UIApplication.IdleTimerDisabled Property

The default value of this property is NO. When most apps have no touches as user input for a short period, the system puts the device into a "sleep” state where the screen dims. This is done for the purposes of conserving power. However, apps that don't have user input except for the accelerometer—games, for instance—can, by setting this property to YES, disable the “idle timer” to avert system sleep.

| IMPORTANT

You should set this property only if necessary and should be sure to reset it to NO when the need no longer exists. Most apps should let the system turn off the screen when the idle timer elapses. This includes audio apps. With appropriate use of Audio Session Services, playback and recording proceed uninterrupted when the screen turns off. The only apps that should disable the idle timer are mapping apps, games, or programs where the app needs to continue displaying content when user interaction is minimal.

like image 74
SushiHangover Avatar answered Oct 26 '22 02:10

SushiHangover