Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Extremely slow nSyncAndDrawFrame when drawing large Bitmaps

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.

like image 520
Ulrich Scheller Avatar asked Jan 18 '16 10:01

Ulrich Scheller


1 Answers

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.

like image 75
Nathan Osman Avatar answered Oct 28 '22 10:10

Nathan Osman