flet: possible memory leak
Memory leak on simple application
The attached app, appears to leak memory consistently as tabs are opened and closed to view the page. In my tests the memory went up from 40.1MB to 40.9MB after opening and closing 20 or 30 tabs. In my production app it is in the 10’s of megabytes.
You need to install memory_profiler to see the increased usage, the increase is small on only Text elements (for instance) but adding ElevatedButton appears to make the leak bigger.
I have left the app running for hours to test if the GC collects this memory later, but it does not appear to.
Code example to reproduce the issue:
import logging
from memory_profiler import profile
import flet as ft
import flet as ft
@profile(precision=6)
def on_connect(e):
logging.debug("Connected")
@profile(precision=6)
def on_disconnect(e):
logging.debug("Disconnected")
@profile(precision=6)
def on_click(e):
print( "Clicked" )
@profile(precision=6)
def main(page: ft.Page):
page.on_connect = on_connect
page.on_disconnect = on_disconnect
page.controls.append(ft.Text(value="Hello, world!", color="green"))
page.controls.append(ft.ElevatedButton("Click me", on_click=on_click))
page.controls.append(ft.ElevatedButton("Click me", on_click=on_click))
page.controls.append(ft.ElevatedButton("Click me", on_click=on_click))
page.controls.append(ft.ElevatedButton("Click me", on_click=on_click))
page.controls.append(ft.ElevatedButton("Click me", on_click=on_click))
page.controls.append(ft.Text(value="Hello, world!", color="green"))
page.controls.append(ft.Text(value="Hello, world!", color="green"))
page.controls.append(ft.Text(value="Hello, world!", color="green"))
page.update()
ft.app(target=main, view=ft.WEB_BROWSER)
This is the memory dump on first connect:
Line # Mem usage Increment Occurrences Line Contents
=============================================================
23 40.140625 MiB 40.140625 MiB 1 @profile(precision=6)
24 def main(page: ft.Page):
25 40.140625 MiB 0.000000 MiB 1 page.on_connect = on_connect
26 40.140625 MiB 0.000000 MiB 1 page.on_disconnect = on_disconnect
27 40.140625 MiB 0.000000 MiB 1 page.controls.append(ft.Text(value="Hello, world!", color="green"))
28 40.140625 MiB 0.000000 MiB 1 page.controls.append(ft.ElevatedButton("Click me", on_click=on_click))
29 40.140625 MiB 0.000000 MiB 1 page.controls.append(ft.ElevatedButton("Click me", on_click=on_click))
30 40.140625 MiB 0.000000 MiB 1 page.controls.append(ft.ElevatedButton("Click me", on_click=on_click))
31 40.140625 MiB 0.000000 MiB 1 page.controls.append(ft.ElevatedButton("Click me", on_click=on_click))
32 40.140625 MiB 0.000000 MiB 1 page.controls.append(ft.ElevatedButton("Click me", on_click=on_click))
33 40.140625 MiB 0.000000 MiB 1 page.controls.append(ft.Text(value="Hello, world!", color="green"))
34 40.140625 MiB 0.000000 MiB 1 page.controls.append(ft.Text(value="Hello, world!", color="green"))
35 40.140625 MiB 0.000000 MiB 1 page.controls.append(ft.Text(value="Hello, world!", color="green"))
36 40.140625 MiB 0.000000 MiB 1 page.update()
This is the memory dump 20 or 30 tabs later (all opened tabs are closed and a single connection is made again):
Line # Mem usage Increment Occurrences Line Contents
=============================================================
23 40.906250 MiB 40.906250 MiB 1 @profile(precision=6)
24 def main(page: ft.Page):
25 40.906250 MiB 0.000000 MiB 1 page.on_connect = on_connect
26 40.906250 MiB 0.000000 MiB 1 page.on_disconnect = on_disconnect
27 40.906250 MiB 0.000000 MiB 1 page.controls.append(ft.Text(value="Hello, world!", color="green"))
28 40.906250 MiB 0.000000 MiB 1 page.controls.append(ft.ElevatedButton("Click me", on_click=on_click))
29 40.906250 MiB 0.000000 MiB 1 page.controls.append(ft.ElevatedButton("Click me", on_click=on_click))
30 40.906250 MiB 0.000000 MiB 1 page.controls.append(ft.ElevatedButton("Click me", on_click=on_click))
31 40.906250 MiB 0.000000 MiB 1 page.controls.append(ft.ElevatedButton("Click me", on_click=on_click))
32 40.906250 MiB 0.000000 MiB 1 page.controls.append(ft.ElevatedButton("Click me", on_click=on_click))
33 40.906250 MiB 0.000000 MiB 1 page.controls.append(ft.Text(value="Hello, world!", color="green"))
34 40.906250 MiB 0.000000 MiB 1 page.controls.append(ft.Text(value="Hello, world!", color="green"))
35 40.921875 MiB 0.015625 MiB 1 page.controls.append(ft.Text(value="Hello, world!", color="green"))
36 40.921875 MiB 0.000000 MiB 1 page.update()
Describe the results you expected: Expected memory to climb on new tab but to drop to original levels on close tab.
Additional information you deem important (e.g. issue happens only occasionally):
Flet version (pip show flet
):
Name: flet
Version: 0.3.2
Summary: Flet for Python - easily build interactive multi-platform apps in Python
Home-page:
Author:
Author-email: Appveyor Systems Inc. <hello@flet.dev>
License: MIT
Location: /Users/gregor.brandt/Documents/Startbridge/web-app2/fe_env/lib/python3.11/site-packages
Requires: beartype, oauthlib, packaging, repath, requests, watchdog, websocket-client
Required-by:
Operating system:
MacOS 13.1, using Firefox as browser
Additional environment details:
About this issue
- Original URL
- State: closed
- Created a year ago
- Reactions: 1
- Comments: 15 (7 by maintainers)
Commits related to this issue
- Changelog updated with memory leak fixes Fix #1223, Fix #969 — committed to flet-dev/flet by FeodorFitsner a year ago
To verify that memory is released when a user session is “closed” I used the following application:
The trick there is
Text.data
value which “eats” 128 MB of RAM for each user session.Additionally, I set session lifetime to 1 minute via environment variable:
Running the app and opening 5 tabs I can see
python
process takes 669 MB:Closing all 5 tabs and waiting for 1 minute I can observe “close” event handler called for all 5 sessions:
python
process takes 29 MB (669 - 128 * 5):I’ve managed to fix it! Will be in tomorrow’s release.