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

How to properly update the menu without leaking memory? #216

Open
israelsucks opened this issue Aug 29, 2024 · 1 comment
Open

How to properly update the menu without leaking memory? #216

israelsucks opened this issue Aug 29, 2024 · 1 comment

Comments

@israelsucks
Copy link

israelsucks commented Aug 29, 2024

Hello,

I've spotted my app which updates its menu regularly reaches multiple GB's of memory over time.

Here is an example code similar to my code's logic, which uses exaggerated values for quick demonstration purposes:

#!/usr/bin/env python3

import rumps
import time

testinterval=0.1

class AwesomeStatusBarApp(rumps.App):

    def __init__(self):
        super(AwesomeStatusBarApp, self).__init__("myapp")
        self.menu = [f"hello"]

    @rumps.timer(testinterval)
    def sayhi(self, _):
        mylist = []
        for i in range(1000):
            mylist += ['time', str(time.time())*10, None]

        # reset menu
        self.menu.clear()

        self.menu = mylist # or self.menu.update(mylist), doesn't matter

if __name__ == "__main__":
    AwesomeStatusBarApp().run()

If you look at Activity Monitor, you'll see its memory grows indefinitely. I've also tried iterating over menu keys() and deleting them but didn't fix the leak.

Am I doing something wrong or is it the rumps which leaks memory under the hood?

@SKaplanOfficial
Copy link
Contributor

Not sure exactly where the leak occurs (whether in rumps or in the underlying pyobjc bridge), but to get around it you can modify menu items in-place rather than remake the whole menu each time, like so:

import rumps
import time

testinterval=0.1

class AwesomeStatusBarApp(rumps.App):

    def __init__(self):
        super(AwesomeStatusBarApp, self).__init__("myapp")
        self.menu = [x for x in range(1000)]

    @rumps.timer(testinterval)
    def sayhi(self, _):
        for (_, item) in self.menu.items():
          item.title = f"time {time.time()}"

if __name__ == "__main__":
    AwesomeStatusBarApp().run()

This hovers around ~35.0 MB on my machine.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

No branches or pull requests

2 participants