Extremely slow nSyncAndDrawFrame when drawing large Bitmaps
Asked Answered
F

3

11

I want to optimize a parallax scrolling view with multiple large Bitmaps. On my Nexus 5, everything is smooth and the Traceview dump looks like this:

Smooth scrolling on Nexus 5

The doFrame() method uses ~18 ms to finish.

However, when using my Nexus 7 or an Android 6 Emulator (Genymotion), the Traceview dump looks like this:

Very laggy rendering on Nexus 7

The nSyncAndDrawFrame method now takes ~300 ms when running the exact same application.

The interesting code part is in onDraw() of the parallax view:

for (int i = 0; i < parallaxConfigManager.getNumberOfLayers(); i++) {
            Bitmap layer = parallaxConfigManager.getLayer(i);
            float dx = (offset * parallaxConfigManager.getScrollSpeedFactorForLayer(i) * imageScaleFactor);
            int offset = Math.round(-parallaxConfigManager.getBoardOffset(i) + dx);
            srcRect.offsetTo(offset, 0);

            int realWidth = getRealWidth(srcRect, layer.getWidth());
            float scaleFactor = destRect.width() / (float) srcRect.width();
            if (realWidth < srcRect.width()) {
                destRect.left       = (int) (scaleFactor * Math.max(0, -srcRect.left));
                destRect.right      = destRect.left + (int) (scaleFactor * realWidth);
            }
            destRect.bottom = Math.min(screenHeight, (int) (scaleFactor * layer.getHeight()));

            canvas.drawBitmap(layer, srcRect, destRect, paint);

            destRect.left = 0;
            destRect.right = screenWidth;
        }

However, this code is fast enough. The slow part is in Androids native nSyncAndDrawFrame().

What could be the problem here? Is there a way to look deeper into this problem? Right now this method is a black box, because I can not see the native call stack.

Frisse answered 18/1, 2016 at 10:7 Comment(1)
After playing around with the program, I believe that my app hits a limit in graphics memory size. When I disable some of the Bitmaps, it starts getting faster. There seems to be more memory available on a Nexus 5 than on a Nexus 7.Frisse
P
3

I stumbled on this question after encountering similar behavior with a large image (1920x933) in a CollapsingToolbarLayout. The profiler revealed that calls to android.view.ThreadedRenderer.nSyncAndDrawFrame() were taking a long time to complete.

Although reducing the image resolution (to 1280x622, for example) will eliminate the problem, there is a way to avoid the issue altogether.

Move your image into the drawable-nodpi folder, which indicates that the image is resolution-independent. The rendering lag should disappear.

Procrustean answered 21/3, 2018 at 3:52 Comment(0)
K
0

In my case, the problem is big images. For example, for background, I have an image with size 800x800, when I reduced this size to 400x400 the problem is gone.

Kermitkermy answered 7/6, 2021 at 7:41 Comment(0)
X
0

On some devices (example: HTC One) I got same situation when drawing constantly changing bitmap. It caused by the copying bitmap to GPU memory. Since last draw my app changes bitmap and after that bitmap constantly copying to GPU memory. If GPU is low on memory, then copying takes a long time. To fix this, have few options:

  • Make bitmap smaller: then GPU memory is enough for constant copying.
  • Disable hardware acceleation (set LAYER_TYPE_SOFTWARE): then system don't need to constantly copy bitmap to GPU memory. I added option to disable HW Acceleration to my app.

To get better understanging you can check this article:

inspect-gpu-rendering

Reference:

hardware-accel

profile-gpu

Xylol answered 13/11, 2023 at 12:54 Comment(0)

© 2022 - 2025 — McMap. All rights reserved.