Huge memory usage by a simple app intended for android

275 views
Skip to first unread message

Greg Yang

unread,
Jul 12, 2013, 9:29:06 PM7/12/13
to kivy-...@googlegroups.com
I'm quite puzzled by why my app keeps taking very much memory. It starts with 70MB but can reach almost 1GB by just a dozen clicks. Is there some important thing I need to know about how Kivy handles memory? For example, is there a memory cost to the kv language? Also what is a good method to debug memory here? 

Kovak

unread,
Jul 12, 2013, 9:46:10 PM7/12/13
to kivy-...@googlegroups.com
You are going to need to share more about what you are doing.

Gabriel Pettier

unread,
Jul 13, 2013, 6:41:12 PM7/13/13
to kivy-...@googlegroups.com
if you have flask installed, you can use the memory debugger module

start your program like this

python main.py -m webdebugger

then open http://localhost:5000 in your browser while your app run, you
should see live memory usage statistics, maybe it can help you.
> --
> 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.
> For more options, visit https://groups.google.com/groups/opt_out.
>
>

Greg Yang

unread,
Jul 18, 2013, 3:06:15 PM7/18/13
to kivy-...@googlegroups.com
OK I figured out the reason it's leaking: the binding automatically created inside the kv language (by the function call_fn) keeps the objects alive by including it in the idmap dictionary in its closure. Here's a simplified example to show what's going on.

from kivy.app import App
from kivy.lang import Builder
from kivy.properties import StringProperty, ObjectProperty
from kivy.uix.button import Button
from kivy.uix.popup import Popup
from kivy.uix.widget import Widget
from objgraph import find_backref_chain, by_type
from pprint import PrettyPrinter
pp = PrettyPrinter().pprint
Builder.load_string('''
<XPop>:
    title: root.xxx.s
''')
class XPop(Popup):
    xxx = ObjectProperty(None)
    
class X(Widget):
    s = StringProperty('hello world')
    @property
    def popup(self):
        pp([find_backref_chain(p, lambda y: y is self) for p in by_type('XPop')])
        return XPop(xxx=self)

class XApp(App):
    def build(self):
        xx = X()
        b = Button(text='pop')
        b.bind(on_release=lambda *args: xx.popup.open())
        return b
    
if __name__ == '__main__':
    XApp().run()
        
If you keep clicking to open the popup, you will see that none of the previous popups were garbage collected. The print output shows the backref chain leading back to the xx object, and essentially it works like xx -> s -> observers of s -> (includes) call_fn -> (closure includes) idmap -> (contains) the popup.

Now if there's a way of accessing this call_fn I can try unbinding it, but is there?

This is particularly troublesome, since I have data models with kivy properties upon which many facets depend upon using kivy bindings through kv. 

Akshay Arora

unread,
Jul 18, 2013, 3:21:16 PM7/18/13
to kivy-...@googlegroups.com
Which version of kivy are you using? Can you try your app with the kivy from github master branch and see if you still get the issue.


Best Regards


--

Greg Yang

unread,
Jul 18, 2013, 3:30:16 PM7/18/13
to kivy-...@googlegroups.com
I'm using kivy171 installed with the zip from the download page (so no manual dependency pulling). Can I just replace the kivy folder in the unzipped kivy171 zip with the master branch or do I still need to build the cython parts? I've had really bad luck with cython in the past few days to get it to work.

Akshay Arora

unread,
Jul 18, 2013, 3:43:19 PM7/18/13
to kivy-...@googlegroups.com
seems like  by_type() also counts weakrefs.

If I add gc.collect() just before pp([find... line the output is always `[]`

Best Regards

Akshay Arora

unread,
Jul 18, 2013, 3:45:29 PM7/18/13
to kivy-...@googlegroups.com
Forgot to mention I'm on the latest dev and you can follow the steps entioned here to get the dev version http://kivy.org/docs/installation/installation-windows.html#use-development-kivy

Best Regards

Greg Yang

unread,
Jul 18, 2013, 7:12:40 PM7/18/13
to kivy-...@googlegroups.com
Yep I got the master branch installed, and that cleared the above example, but my app is still leaking. I dug around and found that lang._handlers isn't deleting items correctly with respect to AccordionItem. Try this

from inspect import ismodule
from kivy.app import App
from kivy.lang import Builder
from kivy.properties import StringProperty, ObjectProperty
from kivy.uix.button import Button
from kivy.uix.popup import Popup
from kivy.uix.widget import Widget
from objgraph import find_backref_chain, by_type
from pprint import PrettyPrinter
import gc
pp = PrettyPrinter().pprint
Builder.load_string('''
<XPop>:
    title: root.xxx.s
    Accordion:
        AccordionItem:
            title: 'hello'
''')
class XPop(Popup):
    xxx = ObjectProperty(None)
    
class X(Widget):
    s = StringProperty('hello world')
    @property
    def popup(self):
        pp([(i, 
#              find_backref_chain(p, ismodule)
            p
             ) for i, p in enumerate(by_type('XPop'))])
        gc.collect()
        return XPop(xxx=self)

class XApp(App):
    def build(self):
        xx = X()
        b = Button(text='pop')
        b.bind(on_release=lambda *args: xx.popup.open())
        return b
    
if __name__ == '__main__':
    XApp().run()
        
If you uncomment the find_backref_chain, you'll see that the leak goes through lang._handlers.

Greg Yang

unread,
Jul 20, 2013, 12:41:27 AM7/20/13
to kivy-...@googlegroups.com
Let me know if this issue gets resolved in a new version of kivy, or a workaround is found. This will be crucial if I want my app to function at all! Thanks!

Akshay Arora

unread,
Jul 20, 2013, 2:46:10 AM7/20/13
to kivy-...@googlegroups.com
Could you please report this on github.com/kivy/kivy/issues.

Best Regards
Reply all
Reply to author
Forward
0 new messages