Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Extremely LowFPS when using KivyMD in low-end devices #812

Open
AM-ash-OR-AM-I opened this issue Feb 6, 2021 · 38 comments
Open

Extremely LowFPS when using KivyMD in low-end devices #812

AM-ash-OR-AM-I opened this issue Feb 6, 2021 · 38 comments
Labels
Architecture: arm64-v8a Status: Needs analysis Issue needs to be analyzed if it's real

Comments

@AM-ash-OR-AM-I
Copy link

AM-ash-OR-AM-I commented Feb 6, 2021

Description of the Bug

I've built a kivymd App but problem is extreme Frame drop lot, specially on low end devices.. Even when other apps that aren't created using kivymd work absolutely normally. It might be caused by SDL2 but what I know for sure is the earlier version of KivyMD like the one Demo in playstore work fine in lowend devices. Also lag is in general for all things I recorded only nav drawer as its 60fps video and max size is 10 MB to upload.

Here are 2 videos showing problem.

VIDEOS

###Low-end processor(SD 430)
https://user-images.githubusercontent.com/59698257/107117182-6f846080-689e-11eb-8abf-ce3f61f7ba4b.mp4

###Mid-range processor(Snapdragon 660)
https://user-images.githubusercontent.com/59698257/107116913-875ae500-689c-11eb-9986-1a4e715267bd.mp4

Versions

  • OS: Android
  • Python: 3.7
  • Kivy: 2.0.0rc1
  • KivyMD: Custom version forked from master.

P.S. Any solution other than downgrading to previous version is much appreciated.

@AM-ash-OR-AM-I AM-ash-OR-AM-I changed the title Extreme lag when using KivyMD in low-end devices Extremely LowFPS when using KivyMD in low-end devices Feb 6, 2021
@HeaTTheatR
Copy link
Member

HeaTTheatR commented Feb 6, 2021

@AM-ash-OR-AM-I In the video that you attached, I did not see that applications created using the KivyMD library slow down ...

@AM-ash-OR-AM-I
Copy link
Author

@AM-ash-OR-AM-I In the video that you attached, I did not see that applications created using the KivyMD library slow down ...

The app that u saw i.e. passlock was made by me using kivymd

@HeaTTheatR
Copy link
Member

@AM-ash-OR-AM-I I didn't see any problems in your videos ...

@AM-ash-OR-AM-I
Copy link
Author

AM-ash-OR-AM-I commented Feb 6, 2021

@AM-ash-OR-AM-I In the video that you attached, I did not see that applications created using the KivyMD library slow down ...

Also I noted that lag in navigation drawer nullifies if phone is connected to laptop via USB(Due to charging? but this doesn't not work with any other external source for charging). However in loweend devices lag is still

@AM-ash-OR-AM-I I didn't see any problems in your videos ...

If u see the video closely preferably in a smartphone screen you will see how smooth apps like Gmail were while My app(using KivyMD) was having Frame Drops.. See the low end device video with my app vs Gmail navigation drawer

@HeaTTheatR
Copy link
Member

@AM-ash-OR-AM-I I do not understand the essence of your problem ...

@AM-ash-OR-AM-I
Copy link
Author

@AM-ash-OR-AM-I I do not understand the essence of your problem ...

The problem is when I am tapping on navigation drawer and in general all UI Elements there is either a delay or frame drop while using my app causing jittering effect and that makes it unusable on all the low end devices..

@HeaTTheatR
Copy link
Member

@AM-ash-OR-AM-I I don't understand what you are talking about ...

@AM-ash-OR-AM-I
Copy link
Author

20210206_182036.mp4

I've uploaded the video once again hope you can see it when Navigation drawer opens there is a clear evident frame drop in UI.(I've used gmail as Reference to show the frame drop in my app) If u want I can provide code of Navigation drawer but still u might not see problem as You might be using mid-range or high-end devices.

@HeaTTheatR
Copy link
Member

@AM-ash-OR-AM-I Try building an app with FPS monitoring...

@AM-ash-OR-AM-I
Copy link
Author

@AM-ash-OR-AM-I Try building an app with FPS monitoring...

20210206_195340.mp4

See this still I'm getting less than 20 fps ...

@HeaTTheatR
Copy link
Member

@AM-ash-OR-AM-I I can't do anything with these...

@HeaTTheatR HeaTTheatR added the Status: Needs analysis Issue needs to be analyzed if it's real label Feb 6, 2021
@HeaTTheatR
Copy link
Member

@podraco
Copy link
Member

podraco commented Feb 6, 2021

For the analysis we need to know the spects of the device you're using
Ram
Cpu
Gpu
Ram
Model
Company

@podraco
Copy link
Member

podraco commented Feb 6, 2021

And we also would need to se your kv files

@AM-ash-OR-AM-I
Copy link
Author

AM-ash-OR-AM-I commented Feb 6, 2021

For the analysis we need to know the spects of the device you're using
Ram
Cpu
Gpu
Ram
Model
Company

Okay!

Device1

Moto G5S (low-end) (MORE FPS drop)
Snapdragon 430
3GB
Motorola
Adreno 505(GPU)

Device2

Redmi note7 (Mid-Range)(less FPS drop)
Snapdragon 660
4GB
Xiaomi
Adreno 512

@HeaTTheatR
Copy link
Member

This issue has already been discussed - kivy/python-for-android#200. I see no reason to repeat all this here.

@AM-ash-OR-AM-I
Copy link
Author

This issue has already been discussed - kivy/python-for-android#200. I see no reason to repeat all this here.

I have used that same Kivy version created by @quitegreensky but still the bug persists. The version that I had used was 2.0.0rc1 and I linked exact same version in buildozer as mentioned by him.

@HeaTTheatR
Copy link
Member

HeaTTheatR commented Feb 6, 2021

@AM-ash-OR-AM-I Where in the Kivy issues there is another big discussion on this topic in which a person attached two packages built with different versions of dependencies. In one package the FPS falls steadily, in the other it does not. Only I don't remember the links to this discussion.

@podraco
Copy link
Member

podraco commented Feb 6, 2021

Also, if you use if inside properties instead of events, the comparison will be executed every frame instead of every time the event is launched.

@HeaTTheatR
Copy link
Member

HeaTTheatR commented Feb 6, 2021

@podraco In the KivyMD library, checks occur in the properties of the widget. Especially in the updated MDDatePicker class:
https://github.com/kivymd/KivyMD/blob/master/kivymd/uix/picker.py#L398
https://github.com/kivymd/KivyMD/blob/master/kivymd/uix/picker.py#L666

...

@HeaTTheatR
Copy link
Member

@podraco But it seems to me that you are wrong. Checks don't happen every frame.

@AM-ash-OR-AM-I
Copy link
Author

AM-ash-OR-AM-I commented Feb 6, 2021

Also, if you use if inside properties instead of events, the comparison will be executed every frame instead of every time the event is launched.

MDNavigationDrawer:
    elevation: 0
    swipe_edge_width: 200
    opening_time: 0.4
    closing_time: 0.4
    id: nav_drawer 
    BoxLayout:
        orientation: 'vertical'
        padding: "8dp"
        spacing: "4dp"
      
        TwoLineAvatarListItem:
            id: email
            markup: True
            text: '[b]'+app.emailname
            secondary_text: '[b]'+app.emailaddress if app.emailname!='No account' else ' '
           
        OneLineIconListItem:
            text: "[b]COLORS"
            on_release: app.theme_dialog()
            theme_text_color: "Custom"
            text_color: app.theme_cls.primary_color
                
            IconLeftWidget:
                id: color
                icon: "checkbox-blank-circle"
                on_release: app.theme_dialog()
                theme_text_color: "Custom"
                text_color: app.theme_cls.primary_color
                       
        OneLineIconListItem:
            
            text: "[b]DARK/LIGHT Mode"
            on_release: app.mode('press')
            
            IconLeftWidget:
                id: mode
                icon: "weather-night"
                on_release: app.mode('press')
                
        OneLineIconListItem:
            text: "[b]CHANGE PASSWORD"
            disabled: app.welcome_disable
            on_release:app.change_pass('create')
            theme_text_color: "Custom"
            text_color: 1,0,0,1
            
            IconLeftWidget:
                id: password
                icon: "lock"
                on_release:app.change_pass('create')
                theme_text_color: "Custom"
                disabled: app.welcome_disable
                text_color: 1,0,0,1
        OneLineIconListItem:
            id: security_list
            markup : True
            text: "[b]ADVANCED SECURITY"
            on_release: app.check_resume()
            theme_text_color: "Custom"
            text_color: 0,0.6,1,1
            IconLeftWidget:
                id: security
                icon: "shield"
                on_release: app.check_resume()
                theme_text_color: "Custom"
                text_color: 0,0.6,1,1
        OneLineIconListItem:
            text: '[b]BACKUP & RESTORE'
            disabled: app.welcome_disable
            on_release: app.choose('')
            theme_text_color: "Custom"
            text_color: 0,0.8,0.3,1
            IconLeftWidget:
                id: sync
                icon: 'backup-restore'
                on_release: app.choose('')
                theme_text_color: "Custom"
                text_color: 0,0.8,0.3,1
                
        MDSeparator:     
        
        MDRectangleFlatButton:
            id: demo
            text: 'START DEMO'
            theme_text_color: "Custom"
            text_color: app.theme_cls.primary_color if self.text!='STOP DEMO' else [1,0,0,0.7]
            on_release: app.tap_target_cust()if self.text!='STOP DEMO' else app.canceldemo()
            pos_hint: {'center_x':0.5}
        
        ScrollView:

Here's the Kv file for the Navigation drawer

@podraco
Copy link
Member

podraco commented Feb 6, 2021

@HeaTTheatR well, i seen how if you get for example:

widget:
    id:test_widget
    property; something if condition else value

will execute every frame
and when you do

on_condition_related_property:
    test_widget.property= something if condition else value

Will only execute when the on_condition_related_property changes, instead of every other frame. The kivy clock even tells you when you have too many instructions at the same time.

@HeaTTheatR
Copy link
Member

HeaTTheatR commented Feb 6, 2021

@podraco
Seems to me that you are wrong:

from kivy.lang import Builder

from kivymd.app import MDApp

KV = '''
MDScreen:
    on_touch_down:
        app.theme_cls.theme_style = "Dark" \
         if app.theme_cls.theme_style == "Light" else "Light"

    MDLabel:
        halign: "center"
        text:
            app.get_dark() \
            if app.theme_cls.theme_style == "Dark" else app.get_light()
'''


class Example(MDApp):
    def build(self):
        return Builder.load_string(KV)

    def get_light(self):
        print("Method `get_light` is called")
        return "Light"

    def get_dark(self):
        print("Method `get_dark` is called")
        return "Dark"


Example().run()

@podraco
Copy link
Member

podraco commented Feb 6, 2021

well, it seems i was wrong, thanks.

@Blaygor
Copy link

Blaygor commented Feb 10, 2021

I've just encountered this myself, however the problem is only present on 64 Bit builds (arm64-v8a). The exact same code, running on armabi-v7a, runs flawlessly. 64 bit build just tanks the framerate to unacceptable levels on both of my devices (Galaxy S7 and Galaxy S9) EDIT: update with video https://user-images.githubusercontent.com/74840429/107521629-e4d99380-6c06-11eb-9b42-7b5402f022db.mp4

@HeaTTheatR
Copy link
Member

@Blaygor Thanks for the tests you did!

@AM-ash-OR-AM-I
Copy link
Author

AM-ash-OR-AM-I commented Feb 11, 2021

I've just encountered this myself, however the problem is only present on 64 Bit builds (arm64-v8a). The exact same code, running on armabi-v7a, runs flawlessly. 64 bit build just tanks the framerate to unacceptable levels on both of my devices (Galaxy S7 and Galaxy S9) EDIT: update with video https://user-images.githubusercontent.com/74840429/107521629-e4d99380-6c06-11eb-9b42-7b5402f022db.mp4

@Blaygor
Does the arm-v7a has any other problems? Does it run on 32-bit? Can you tell me how do I make a build of arm-v7a in buildozer?

@AM-ash-OR-AM-I
Copy link
Author

@Blaygor Thanks for the tests you did!

@HeaTTheatR Can you please Help me out on how can I build an apk in arm-v7a? I'm new to buildozer so I don't quite know how to do it...

@Blaygor
Copy link

Blaygor commented Feb 11, 2021

Here's the issue right now. Google's play store will only accept 64 bit builds (you can include a 32bit build but a 64 bit build is necessary at first). With the processors you mentioned, they're both 64 bit. I would verify that your devices are running at 64 bit with something like 64 Bit Checker. In the buildozer.spec, there is a line which allows you to change architectures.

android.arch = arm64-v8a

If your spec file says this, then you're building a 64 bit application. You need to change arm64-v8a to armeabi-v7a to build the 32 bit application.

In my 32 bit application, the navigation drawer does not cause any significant FPS drop. The same code, compiled in 64 bit, tanks the FPS to single digits.

@AM-ash-OR-AM-I
Copy link
Author

AM-ash-OR-AM-I commented Feb 11, 2021

Here's the issue right now. Google's play store will only accept 64 bit builds (you can include a 32bit build but a 64 bit build is necessary at first). With the processors you mentioned, they're both 64 bit. I would verify that your devices are running at 64 bit with something like 64 Bit Checker. In the buildozer.spec, there is a line which allows you to change architectures.

android.arch = arm64-v8a

If your spec file says this, then you're building a 64 bit application. You need to change arm64-v8a to armeabi-v7a to build the 32 bit application.

In my 32 bit application, the navigation drawer does not cause any significant FPS drop. The same code, compiled in 64 bit, tanks the FPS to single digits.

I actually didn't pay a lot attention to the version and as it turns out the version in which I'm building it is indeed arm v7a by default I just didn't pay attention to that and even then Fps drop is visible (in low end processor). Key thing to note is fps is around 20fps while using Snapdragon 430 and 45fps while using Snapdragon 660 though 2nd one is acceptable but still it should be locked at 60fps all the time.

@AM-ash-OR-AM-I
Copy link
Author

Here's the issue right now. Google's play store will only accept 64 bit builds (you can include a 32bit build but a 64 bit build is necessary at first). With the processors you mentioned, they're both 64 bit. I would verify that your devices are running at 64 bit with something like 64 Bit Checker. In the buildozer.spec, there is a line which allows you to change architectures.
android.arch = arm64-v8a
If your spec file says this, then you're building a 64 bit application. You need to change arm64-v8a to armeabi-v7a to build the 32 bit application.
In my 32 bit application, the navigation drawer does not cause any significant FPS drop. The same code, compiled in 64 bit, tanks the FPS to single digits.

I actually didn't pay a lot attention to the version and as it turns out the version in which I'm building it is indeed arm v7a by default I just didn't pay attention to that and even then Fps drop is visible (in low end processor)

Key thing to note here

Description of the Bug

I've built a kivymd App but problem is extreme Frame drop lot, specially on low end devices.. Even when other apps that aren't created using kivymd work absolutely normally. It might be caused by SDL2 but what I know for sure is the earlier version of KivyMD like the one Demo in playstore work fine in lowend devices. Also lag is in general for all things I recorded only nav drawer as its 60fps video and max size is 10 MB to upload.

Here are 2 videos showing problem.

VIDEOS

###Low-end processor(SD 430)
https://user-images.githubusercontent.com/59698257/107117182-6f846080-689e-11eb-8abf-ce3f61f7ba4b.mp4

###Mid-range processor(Snapdragon 660)
https://user-images.githubusercontent.com/59698257/107116913-875ae500-689c-11eb-9986-1a4e715267bd.mp4

Versions

  • OS: Android
  • Python: 3.7
  • Kivy: 2.0.0rc1
  • KivyMD: Custom version forked from master.

P.S. Any solution other than downgrading to previous version is much appreciated.

Also as I mentioned here the old kivymd version that had the demo app in playstore was working almost more than 40fps(approximately to my eyes) all the time. There was no major frame drop in low end device that means something in all of the updates to kivymd or kivy itself might have caused it. Just a speculation...

@podraco
Copy link
Member

podraco commented Feb 11, 2021

There are many variables for us to be able to analyze that environment, the old version was made with different kivy, kivymd and android API
also, there might be the possibility that the memory itself is the cause of the frame drop.

@podraco
Copy link
Member

podraco commented Feb 11, 2021

also, anyone knows if async works with android?

@podraco
Copy link
Member

podraco commented Feb 18, 2021

So, after some research, i believe this issue is more of a processor sided issue than form kivyMD, since the instruction set used are way too different for us to include into kivyMD.
Pillow relies on basic instructions that can be compiled between architectures because they use the common instructions.
But, devices in the side of ARM doesn't share the same basic instruction set.

The needed functions are SSE4+ based to improve the app UI but, such devices don't have those instructions.
You can check this by reading android ABI help page.

Each architecture has its own instruction set implementation and a list with do and don't.

Even so, some devices adds some interesting architectures to improve data management and process time. But are too specific to be included in a common repo like KivyMD.

If someone is interested, they could add those improvements to pillow directly, I'm pretty sure they will appreciate the help.
By the mean time, I'll be looking for some trick from the old school to improve the processing time required.

So, in resume.
to solve this, the ideal approach would be that pillow added some SIMD (Single Instruction, Multiple Data) able instructions for ARMv7 and v8 (based on NEON for aarch64 = arm64v8, SSE,SSSE for x86 and x86_64; and VFPv3-D32 for armeabi-v7a)
and for us to add som tricks and ilussions to improve the UX.

@AM-ash-OR-AM-I
Copy link
Author

AM-ash-OR-AM-I commented Feb 18, 2021

So, after some research, i believe this issue is more of a processor sided issue than form kivyMD, since the instruction set used are way too different for us to include into kivyMD.
Pillow relies on basic instructions that can be compiled between architectures because they use the common instructions.
But, devices in the side of ARM doesn't share the same basic instruction set.

The needed functions are SSE4+ based to improve the app UI but, such devices don't have those instructions.
You can check this by reading android ABI help page.

Each architecture has its own instruction set implementation and a list with do and don't.

Even so, some devices adds some interesting architectures to improve data management and process time. But are too specific to be included in a common repo like KivyMD.

If someone is interested, they could add those improvements to pillow directly, I'm pretty sure they will appreciate the help.
By the mean time, I'll be looking for some trick from the old school to improve the processing time required.

So, in resume.
to solve this, the ideal approach would be that pillow added some SIMD (Single Instruction, Multiple Data) able instructions for ARMv7 and v8 (based on NEON for aarch64 = arm64v8, SSE,SSSE for x86 and x86_64; and VFPv3-D32 for armeabi-v7a)
and for us to add som tricks and ilussions to improve the UX.

Okay, so inshort it means apps in KivyMD aren't directly optimised due to different architecture used in processor? And Just to emphasize this we can see apps build by Google ( and those in playstore) run absolutely fluid on the low-end phones. So it must be a optimisation issue. .

Hope, you could add some changes to atleast minimize frame drop.. And Looking forward to see changes in Pillow to add some SIMD that you need.

@podraco
Copy link
Member

podraco commented Feb 20, 2021

kivyMD doesn't optimize at all because kivyMd is a top-level framework, it doesn't compile any code, if you see, most of our code is purely python.

You could try and use pypy directly, but I'm not sure how well does that work.

Pillow is the base class for kivy, it manages arrays and textures used to be displayed on screen.
I'm not sure if pillow have any optimization options for ARM, but as a quick tip, you can edit the python for android recipe directly stored in .buildozer/recipes/pillow and play with the compiler flags.

What kivyMD could do is fake some textures or a hard-coded compression of them. But this leads to some strange lines and behaviors displayed, due to mipmapping issues, and, any device not able of mipmapping, won't be compatible with kivyMD at first hand. but that configuration is on the kivy project side.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
Architecture: arm64-v8a Status: Needs analysis Issue needs to be analyzed if it's real
Projects
None yet
Development

No branches or pull requests

4 participants