10

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.

user229044
  • 232,980
  • 40
  • 330
  • 338
Ulrich Scheller
  • 11,800
  • 5
  • 28
  • 32
  • 2
    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. – Ulrich Scheller Jan 20 '16 at 08:53

2 Answers2

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.

Nathan Osman
  • 71,149
  • 71
  • 256
  • 361
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.

iscariot
  • 434
  • 7
  • 14