-
Notifications
You must be signed in to change notification settings - Fork 446
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
possible memory leak #969
Comments
Thanks for bringing up this subject! I'm going to take a look and then we can discuss it here. |
@FeodorFitsner When exactly is |
The following program shows the leak as clearly as possible. It is idiomatic flet code, as per examples. If you run the code below and close the browser tab, you will see that the user control is never deleted. In this case the thread runs for ever. Neither import os
import threading
from datetime import datetime
import flet as ft
class GreeterControl(ft.UserControl):
def __init__(self):
super().__init__()
self.timer = threading.Timer(1, self.on_timer)
def __del__(self):
print("Hello from __del__")
self.timer.cancel()
def build(self):
return ft.Text("Hello!")
def did_mount(self):
print("Hello from did_mount")
self.timer.start()
def will_unmount(self):
print("Hello from will_unmount")
self.timer.cancel()
def on_timer(self):
print(f"{datetime.now()} Hello from on_timer - {id(self)}")
self.timer = threading.Timer(1, self.on_timer)
self.timer.start()
def main( page: ft.Page):
def on_disconnect( _: ft.ControlEvent):
print("Hello from on_disconnect")
def on_connect( _: ft.ControlEvent):
print("Hello from on_connect")
def on_close( _: ft.ControlEvent):
print("Hello from on_close")
page.on_disconnect = on_disconnect
page.on_connect = on_connect
page.on_close = on_close
page.add( GreeterControl( ) )
page.update()
os.environ["FLET_APP_LIFETIME_MINUTES"] = "1"
if __name__ == "__main__":
ft.app( target=main, view=ft.WEB_BROWSER ) |
Also, you would think that you can delete controls on the What does work is to clear the control list in |
what error do you get when calling |
Right, as the session is already deleted on Flet web server side. So, the solution would be in |
I think that would work. I think that maybe a helper function |
What also has to occur is that whatever is holding the reference to the control needs to lose the reference so that the control can be garbage collected. |
A reference to a I don't know, is there anything else preventing it from proper garbage-collecting? |
I have to test after this first fix is out...but I think that that the |
Any movement forward on this, I'd love to help with the testing. it is a major blocker for my app. |
I'm currently looking into that. Want to check it for 0.5.0 release. |
I've managed to fix it! Will be in tomorrow's release. |
To verify that memory is released when a user session is "closed" I used the following application: import logging
import flet as ft
from memory_profiler import profile
@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_close(e):
logging.debug("Closed")
@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.on_close = on_close
page.controls.append(
ft.Text(data=f"a" * (1024 * 1024 * 128), 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) The trick there is Additionally, I set session lifetime to 1 minute via environment variable:
Running the app and opening 5 tabs I can see Closing all 5 tabs and waiting for 1 minute I can observe "close" event handler called for all 5 sessions:
|
* Line chart initial commit * More chart classes * LineChart Python model * Use custom flutter_svg library * aspect_ratio added to all controls * AspectRatio on Flutter side * Changed flutter_svg reference to flet-fixes branch * Charts moved to flet-core package * Remove --allow-releaseinfo-change flag * LineChart Python classes * LineChart stub control added * LineChart prototype * LineChart complete * LineChart datapoint tooltips * LineChart.on_chart_event * Fix tests * shadow and dash_pattern * spot indicators for line chart * Dot marker style * Line chart point * Point gradients * Show below/above lines * selected below line * selected points on non-interactive charts * Linechart adjusted for "monthly sales" example * pip install --upgrade pip * cutoff Y * point_line_start/end * Renamings for BarChart * BarChart data model python and dart * BarChart first steps * BarChart tooltip and touch event * PieChart * remove show_title from piechart * remove interactive and border from piechart * Added shadow to TextStyle * Automatic sizing of line and bar charts * Bump Flet version to 0.5.0, update changelog * Bump Pyodide 0.23 Closes flet-dev#1241 * Updated changelog with Pyodide 0.23 * Fixed memory leak when deleting orphaned controls Fix flet-dev#1223 * Remove all page references * Reliably remove closed sessions from memory * Changelog updated with memory leak fixes Fix flet-dev#1223, Fix flet-dev#969 * Cleaup imports
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:
This is the memory dump on first connect:
This is the memory dump 20 or 30 tabs later (all opened tabs are closed and a single connection is made again):
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
):Operating system:
MacOS 13.1, using Firefox as browser
Additional environment details:
The text was updated successfully, but these errors were encountered: