Skip to content

Page navigation with whole page 'background-image' very slow #3538

Closed

Description

@neuspadrin

Issue

From what I can tell having an image set via css background-image greatly affects navigation performance. I can recreate this in both base nativescript and nativescript with angular routers on Android. When you set background-image and attempt to navigate the page lags 1-3 seconds before starting to navigate and is slow to be responsive again. The lag is dependent on how large of an image you use, but even with a small 10kb image as the background I was still noticing a hit. Max size I tried was 250kb and it was very very slow.

I looked around and noticed the previous navigation performance issues on Android back on 2.3, but it seems like those were resolved with 2.4. Didn't see anything else on searches similar to this.

Platforms affected

Android for sure, unsure about iOS as I don't have one.

Version info:

nativescript: 2.4.2
tns-core-modules: 2.4.4
tns-android: 2.4.1

How to recreate

Set up two pages and a button to navigate between them. Set the "background-image" of both pages to be some image (200kb size or so will really show it, smaller sizes still will be noticeable). Attempt to navigate back and forth. There should be a large lag between clicking the button and the actual navigation.

Workaround

A workaround seems to be if you instead do something like:

<AbsoluteLayout>
    <Image src="~/path/to/bg.png" stretch="aspectFill" left="0" top="0" width="100%" height="100%"></Image>
    <StackLayout top="0" left="0" width="100%" height="100%">
        ... usual content here
    </StackLayout>
</AbsoluteLayout>

Then everything goes back to snappy fast even though the display will essentially show the exact same thing.

Activity

  1. NickIliev commented on Jan 30, 2017

    @NickIliev
    Contributor

    Hello @neuspadrin

    I've tested the described scenario here with 243KB image used as a background-image for both man-page and sub-page. After some testing, I was not able to reproduce slow navigation transactions (tested on real devices with API19 and API23 and also on some emulators).

    Can you please share with us more details on how to reproduce this case (including a code snippet and the environment on what you are testing e.g. the Android API level of your device/emulator).

  2. neuspadrin commented on Jan 31, 2017

    @neuspadrin
    Author

    Thanks for taking a look at this @NickIliev , I downloaded your scenario and gave it a shot on my devices. I can still notice it slightly with your example. While the demo is a bit snappier then what I had been seeing (and I tried to recreate now but I can't seem to fully) you can still notice that on tap it lags a bit more than it should be. A good comparison is if you set the css to:

    Page {
        background-image: url("~/images/background.jpg");
        background-repeat: no-repeat;
        background-size: cover;
    }

    Try with the above a few times, then try commenting out the page css, and trying the updated page xml files below like my workaround mentions:

    <Page xmlns="http://schemas.nativescript.org/tns.xsd" navigatingTo="navigatingTo">
        <AbsoluteLayout>
            <Image src="~/images/background.jpg" stretch="aspectFill" left="0" top="0" width="100%" height="100%"></Image>
            <StackLayout top="0" left="0" width="100%" height="100%">
                <Label text="Tap the button" class="h1 text-center"/>
                <Button text="goToSub" tap="goToSub" class="btn btn-primary btn-active"/>
            </StackLayout>
        </AbsoluteLayout>
    </Page>

    and

    <Page xmlns="http://www.nativescript.org/tns.xsd" loaded="onLoaded" navigatedTo="onNavigatedTo">
        <AbsoluteLayout>
            <Image src="~/images/background.jpg" stretch="aspectFill" left="0" top="0" width="100%" height="100%"></Image>
            <StackLayout top="0" left="0" width="100%" height="100%">
                <Label text="Sub Page" fontSize="48" textWrap="true" />
                <Button text="goBack" tap="goBack" />
            </StackLayout>
        </AbsoluteLayout>
    </Page>

    There is a definite reaction "feel" difference (and had been even worse my previous attempts). To make things worse, while trying your example I actually even hit a OOM exception toggling back and forth a few times rapidly on my actual device. Attached stack below. I can repeat this constantly with toggling back and forth of background-image getting the OOM now, but constant faster switching with the workaround code seems to handle the memory just fine?

    Emulator: API 23
    Physical device: API 24

    An uncaught Exception occurred on "main" thread.
    java.lang.OutOfMemoryError: Failed to allocate a 241932 byte allocation with 189424 free bytes and 184KB until OOM
    	at dalvik.system.VMRuntime.newNonMovableArray(Native Method)
    	at android.graphics.Bitmap.nativeCreate(Native Method)
    	at android.graphics.Bitmap.createBitmap(Bitmap.java:879)
    	at android.graphics.Bitmap.createBitmap(Bitmap.java:856)
    	at android.graphics.Bitmap.createBitmap(Bitmap.java:823)
    	at android.graphics.drawable.RippleDrawable.updateMaskShaderIfNeeded(RippleDrawable.java:769)
    	at android.graphics.drawable.RippleDrawable.drawBackgroundAndRipples(RippleDrawable.java:853)
    	at android.graphics.drawable.RippleDrawable.draw(RippleDrawable.java:693)
    	at android.view.View.getDrawableRenderNode(View.java:17310)
    	at android.view.View.drawBackground(View.java:17246)
    	at android.view.View.draw(View.java:17058)
    	at android.view.View.updateDisplayListIfDirty(View.java:16049)
    	at android.view.ViewGroup.recreateChildDisplayList(ViewGroup.java:3748)
    	at android.view.ViewGroup.dispatchGetDisplayList(ViewGroup.java:3728)
    	at android.view.View.updateDisplayListIfDirty(View.java:16012)
    	at android.view.ViewGroup.recreateChildDisplayList(ViewGroup.java:3748)
    	at android.view.ViewGroup.dispatchGetDisplayList(ViewGroup.java:3728)
    	at android.view.View.updateDisplayListIfDirty(View.java:16012)
    	at android.view.View.draw(View.java:16833)
    	at android.view.ViewGroup.drawChild(ViewGroup.java:3764)
    	at android.view.ViewGroup.dispatchDraw(ViewGroup.java:3550)
    	at android.view.View.draw(View.java:17070)
    	at android.view.View.updateDisplayListIfDirty(View.java:16049)
    	at android.view.ViewGroup.recreateChildDisplayList(ViewGroup.java:3748)
    	at android.view.ViewGroup.dispatchGetDisplayList(ViewGroup.java:3728)
    	at android.view.View.updateDisplayListIfDirty(View.java:16012)
    	at android.view.ViewGroup.recreateChildDisplayList(ViewGroup.java:3748)
    	at android.view.ViewGroup.dispatchGetDisplayList(ViewGroup.java:3728)
    	at android.view.View.updateDisplayListIfDirty(View.java:16012)
    	at android.view.ViewGroup.recreateChildDisplayList(ViewGroup.java:3748)
    	at android.view.ViewGroup.dispatchGetDisplayList(ViewGroup.java:3728)
    	at android.view.View.updateDisplayListIfDirty(View.java:16012)
    	at android.view.ViewGroup.recreateChildDisplayList(ViewGroup.java:3748)
    	at android.view.ViewGroup.dispatchGetDisplayList(ViewGroup.java:3728)
    	at android.view.View.updateDisplayListIfDirty(View.java:16012)
    	at android.view.ThreadedRenderer.updateViewTreeDisplayList(ThreadedRenderer.java:656)
    	at android.view.ThreadedRenderer.updateRootDisplayList(ThreadedRenderer.java:662)
    	at android.view.ThreadedRenderer.draw(ThreadedRenderer.java:770)
    	at android.view.ViewRootImpl.draw(ViewRootImpl.java:2796)
    	at android.view.ViewRootImpl.performDraw(ViewRootImpl.java:2604)
    	at android.view.ViewRootImpl.performTraversals(ViewRootImpl.java:2211)
    	at android.view.ViewRootImpl.doTraversal(ViewRootImpl.java:1246)
    	at android.view.ViewRootImpl$TraversalRunnable.run(ViewRootImpl.java:6301)
    	at android.view.Choreographer$CallbackRecord.run(Choreographer.java:871)
    	at android.view.Choreographer.doCallbacks(Choreographer.java:683)
    	at android.view.Choreographer.doFrame(Choreographer.java:619)
    	at android.view.Choreographer$FrameDisplayEventReceiver.run(Choreographer.java:857)
    	at android.os.Handler.handleCallback(Handler.java:751)
    	at android.os.Handler.dispatchMessage(Handler.java:95)
    	at android.os.Looper.loop(Looper.java:154)
    	at android.app.ActivityThread.main(ActivityThread.java:6077)
    	at java.lang.reflect.Method.invoke(Native Method)
    	at com.android.internal.os.ZygoteInit$MethodAndArgsCaller.run(ZygoteInit.java:865)
    	at com.android.internal.os.ZygoteInit.main(ZygoteInit.java:755)
    
  3. NickIliev commented on Feb 1, 2017

    @NickIliev
    Contributor

    @neuspadrin thank you for your detailed info! I was able to reproduce the memory leak on my side. We will investigate and come back with further information.

    Sample app to reproduce this behaviour here

    Steps to reproduce:

    • set an image as background-image via CSS
    • Load application and start tracking memory consumption
    adb shell dumpsys meminfo | grep org.nativescript.issue3538
    
    • go back and forward from main-page to sub-page
    • memory rising exponentially until Out of Memory error - navigation becoming "heavier"
  4. NickIliev commented on Feb 21, 2017

    @NickIliev
    Contributor

    reproducible with modules30

  5. hshristov commented on Apr 26, 2017

    @hshristov
    Contributor

    @NickIliev Could you check with latest modules30 (from master)?

  6. added
    ready for testTSC needs to test this and confirm against live production apps and automated test suites
    on Apr 26, 2017
  7. added this to the 3.0 milestone on Apr 26, 2017
  8. NickIliev commented on Apr 26, 2017

    @NickIliev
    Contributor

    @hshristov tested with tns-core-modules-3.1.20174261 and works like a charm!

  9. added and removed
    ready for testTSC needs to test this and confirm against live production apps and automated test suites
    on Apr 26, 2017
  10. lock commented on Aug 28, 2019

    @lock

    This thread has been automatically locked since there has not been any recent activity after it was closed. Please open a new issue for related bugs.

  11. locked and limited conversation to collaborators on Aug 28, 2019
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Metadata

Metadata

Assignees

No one assigned

    Type

    No type

    Projects

    No projects

      Milestone

      Relationships

      None yet

      Development

      No branches or pull requests

      Issue actions