0

Our company develops several games for mobile platforms, including Android. We use OpenGL for all visual items, including UI (more technical details are below).

We have received some weird warnings from Google Play Console in Pre-launch report, like “Your app took 20764 ms to launch”. On the video provided with this report, the game took about a second to start.

After some investigation we found that Android Systrace cannot detect OpenGL draws made from another thread. So Pre-launch tests think (wrongly) that our game is super-slow.

Is there some method to notify the system that a frame is drawn? It’s seems that eglSwapBuffers() is not enough.

There’s a link to the same problem with Cocos2d: https://discuss.cocos2d-x.org/t/frozen-frames-warnings-by-google-play-pre-launch-report-for-3-17-cocos-demo-app/42894

Some details

When a new build is published to Google Play Console, some automated tests are performed on different devices. Results of these tests are available in Pre-launch report section of the Google Play Console.

Starting from beginning of April we receive strange performance warnings on some of devices (always the same ones). Two examples:

  • Startup time: Your app took 20764 ms to launch…
  • Frozen frames: 33.33% of the frames took longer than 700ms to render

Both problems sound dreadful--would have they be true. But when we examined videos of testing, we could not see any problems. All games started pretty fast and ran without visual stuttering.

Systrace report

This is the picture of systrace showing 5 seconds of our game being started (rectangles were drawn by me).

systrace

As you can see, the systrace have found only 4 frames rendered (the pink rect), which were drawn from the RenderThread. But by some reason Android cannot detect our GL draw calls which are performed in another thread (blue rects).

Pre-launch reports also displays only 3 to 4 frames, each 300-400 ms long.

Initialization code

Our game engine runs all game logic and render code in a separate thread. This is simplified initialization code.

The worker thread is created from our Activity’s onStart() overriden method.

public class MyActivity extends Activity
{
    protected Thread worker = null;

    private native void Run();

    @Override
    protected void onStart()
    {
        super.onStart();

        if(worker == null)
        {
            worker = new Thread()
            {
                public void run()
                {
                    Run();
                }
            };

            worker.start();
        }
    }
}

The only thing the thread does is the Run() native function. This function may be resolved into something like this:

void MyActivity::Run()
{
    initApp();

    while(!destroyRequested())
    {
        // Process the game logic.
        if (activated && window != NULL)
        {
            time->process();
            input->process();
            sound->process();
            logic->process();
            graphics->draw();
        }
    }

    clearApp();
}

As you can see, the worker thread constantly spins the update-and-draw loop. Vsync protects the loop from overperforming. Heavy operations like resource loading are done asynchronously to avoid freezes.

From the user side this approach works just fine. Games are loading fast and go smoothly.

Phantômaxx
  • 37,901
  • 21
  • 84
  • 115
  • One solution may be to send from the secondary thread a message to the main thread so as to do rendering in the main thread. Other solution is, because is only ASystrace complaining, to deceive ASystrace, for example with a initial splash screen rendered in the main thread. – Ripi2 Aug 09 '18 at 17:25
  • Yes, we thought about moving render to the main thread. But this will require some extra syncronization code. A simple ping-pong sync may introduce aditional delay, and more complicated version may initially have bugs. Our games are already sold, and the warnings do not (yet) bring any consequences, so we are a little afraid to make serious changes in the engine. – Sergey Ali Aug 09 '18 at 17:48
  • As to render a splash screen, this may help to deal with "20 seconds to start", but it won't probably sovles the warning about frozen frames, because it will just add one more frame to other 3 or 4 found by systrace. Or I've got something wrong? – Sergey Ali Aug 09 '18 at 17:57

0 Answers0