For performance issues the first step is to profile the code there is a discussion here: https://kivy.org/doc/master/api-kivy.app.html#profiling-with-on-start-and-on-stop
Also see: https://docs.python.org/3/library/profile.html
Performance issues are often caused by creating lots of widget instances over and over. For example lets assume you have 500 items you want in the TreeView, you might be creating those 500 widgets when parsing the data and displaying the treeview. A higher performance approach would create all the required widgets, keep them in a list and reuse them rather than recreating them.
Another option would be to look at how to ‘break up’ a long running task into smaller pieces. For example assuming you have 1000 actions to do in your 10 seconds, insert a Clock.schedule_once() for every few 100 actions. Have the callback continue the operation, this lets the Kivy event loop run to process events. You could also take an approach like this and combine it with a progressbar to communicate to the user there is a long running event.
If I had to guess – my guess is you are creating lots of widgets. But don’t guess start by profiling your code.
If you need more help create a minimal, runnable example and share the example with the data that is causing the slow behavior.
Here is a small example of using the profiler. The code creates a large number of spinners and shows the time to create them, and prints the code profile.
from kivy.app import App
from kivy.app import Builder
from kivy.uix.spinner import Spinner
from kivy.core.window import Window
from kivy.clock import Clock
from time import perf_counter
import cProfile
import pstats
kv = """
<OptionsSpinner>:
values: [str(x) for x in range(1, 11)]
BoxLayout:
orientation: 'vertical'
GridLayout:
id: grid
rows:20
cols: 10
Label:
id:label
size_hint_y: None
height: 24
text: 'Test in Progress'
"""
class OptionsSpinner(Spinner):
pass
class SpeedTestApp(App):
def build(self):
Window.fullscreen = 'auto'
return Builder.load_string(kv)
def on_start(self):
Clock.schedule_once(self.create_widgets_for, 1) # wait for fullscreen...
def create_widgets_for(self, dt):
self.profile = cProfile.Profile()
self.profile.enable()
start_time = perf_counter()
r = self.root.ids.grid.rows
c = self.root.ids.grid.cols
for i in range(r * c):
self.root.ids.grid.add_widget(OptionsSpinner(text=f'OS {i}'))
self.for_time = perf_counter() - start_time
self.profile.disable()
stats = pstats.Stats(self.profile)
stats.sort_stats('cumulative')
stats.print_stats(25)
print(f'For loop execution time: {self.for_time:.2f}')
self.root.ids.label.text = f'For loop execution time: {self.for_time:.2f}'
SpeedTestApp().run()
--
You received this message because you are subscribed to the Google Groups "Kivy users support" group.
To unsubscribe from this group and stop receiving emails from it, send an email to kivy-users+...@googlegroups.com.
To view this discussion on the web visit https://groups.google.com/d/msgid/kivy-users/0b715e85-d435-466e-8d0d-1fb39a7ac7c8n%40googlegroups.com.
It is the creation of all of the widgets that go into the Treeview that is taking up most of the time.
The approach I would suggest is to separate the recursive parsing of the JSON and the widget creation.
Parse the JSON and create a list of parameters to go into the treeview nodes. Then create a loop, that processes say 50 lines at a time, and updates a progress bar.
Alternatively if you need to view this kind of data frequently, that is you are viewing different datasets, pre-allocate the widgets and add the data to the pre-allocated widgets. It is the widget creation that is taking most of the time. If you comment out most of the code in MyNode.__init__(), you will see that is where most of the time is being spent.
To view this discussion on the web visit https://groups.google.com/d/msgid/kivy-users/b743cc8c-7f0d-4543-b48d-27a5faa6e697n%40googlegroups.com.
The widget is not changing in your code, only the data in the widget.
Change your __iniit__ so it will work with out getting any data passed in, this will let you separate widget creation and putting data in the widget. You could then create a list of widgets using a list comprehension.
nodes = [MyNode() for _ in range(1000)]
# this would create a list of 1000 MyNode objects.
MyNode instances have a text attribute you could later set the text attribute….
nodes[0].text = ‘The text value’
And then add it to the widget tree…
…add_widget(nodes[0])
If you you need more nodes add them to the list. Never delete the widgets in nodes, just clear the data in them, and use the widgets again. This way you only pay the cost of creating them once.
To view this discussion on the web visit https://groups.google.com/d/msgid/kivy-users/3b22042e-c058-4781-9cb1-bf62ba5f01dcn%40googlegroups.com.