Kivy performance...

664 views
Skip to first unread message

Ryan

unread,
Apr 29, 2012, 11:52:18 PM4/29/12
to kivy-...@googlegroups.com
I'm curious to know how I can improve Kivy's performance ...

I'm interested in getting several hundred (thousand?) images moving around at the same time. Now, I realize this will be expensive to compute, but I was hoping that someone here could enlighten me in to options at improving Kivy's performance... perhaps it's just not possible to do on current hardware?

Still, here's what I'm using for hardware:
- Intel Xeon W3670 (6 cores with hyperthreading) @ 3.2Ghz
- 12GB RAM
- nVidia GTX580
- Windows 7 Professional

I've modified the Pictures demo example to load 100 copies of each image (currently 3 images x 100), added an FPS counter, and made it such that an 'on_touch_move' will move *ALL* images.

Here's what I came up with:

import kivy
kivy.require('1.0.6')

from glob import glob
from random import randint
from os.path import join, dirname
from kivy.app import App
from kivy.logger import Logger
from kivy.uix.scatter import Scatter
from kivy.properties import StringProperty
# FIXME this shouldn't be necessary
from kivy.core.window import Window
from kivy.clock import Clock
from kivy.uix.label import Label


class Picture(Scatter):
    source = StringProperty(None)
    
class PicturesApp(App):

    def build(self):
        # the root is created in pictures.kv
        root = self.root
        self.root.on_touch_move = self.on_touch_move
        
        self.fps_label = Label(halign='left')
        self.root.add_widget(self.fps_label)
        Clock.schedule_interval(self.set_fps, 1.0/60)

        # get any files into images directory
        curdir = dirname(__file__)
        for filename in glob(join(curdir, 'images', '*')):
            try:
                # load the image
                for x in range(100):
                    picture = Picture(source=filename, rotation=randint(-30,30), pos=(randint(0,400), randint(0,400)))
                    # add to the main field
                    root.add_widget(picture)
            except Exception, e:
                Logger.exception('Pictures: Unable to load <%s>' % filename)

    def on_pause(self):
        return True
    
    def on_touch_move(self, touch):
        for p in self.root.children:
            if (p.__class__.__name__ == "Picture" and touch.grab_current != p):
                p.pos = (p.x + touch.dx/2, p.y + touch.dy/2)
                
    def set_fps(self, dt):
        self.fps_label.text = 'Current FPS: ' + str(Clock.get_fps())
        self.fps_label.pos = (-Window.width/2 + 120, Window.height/2 - 40) 


if __name__ in ('__main__', '__android__'):
    PicturesApp().run()


Based on my current hardware, when I do nothing (or if I change the code to move only one image at a time) performance is great!
But if I use the above code, Kivy chugs down to around 10 fps. Also, it seems to be independent of the window size, so it doesn't seem to be a rendering issue, but more of a raw computation issue.

Would I be better off spawning multiple threads to handle the movement?


Ryan

Mathieu Virbel

unread,
May 2, 2012, 7:28:30 AM5/2/12
to kivy-...@googlegroups.com
Interesting.

I would like to know if it's the computation from the on_touch_move, or the graphics computation than came just after the on_touch_move (like all graphics instructions are put in dirty state, and reuploaded or something. or if all of them are recompiled.)
100 doesn't seem big, but still, you can have  (if FPS is limited to 60) 60 touch move = 6000 collision test that involve Matrix computation.

A deeper test would be great to see where it's slowing down exactly.
Also, the 8 cores have no meaning, Kivy is using only one, and Python have GIL so...

Mathieu
Reply all
Reply to author
Forward
0 new messages