Skip to content

Commit b2644e2

Browse files
committed
garbage collection and memory cleanup upon tab closure to prevent memory leak across users
1 parent 83b2de5 commit b2644e2

4 files changed

Lines changed: 30 additions & 17 deletions

File tree

channelmap_generator/__init__.py

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -7,6 +7,6 @@
77

88
from .backend import *
99

10-
__version__ = "0.3.9"
10+
__version__ = "0.3.10"
1111
__author__ = "Maxime Beau"
1212
__email__ = "maxime@princeton.edu"

channelmap_generator/gui/app_util.py

Lines changed: 2 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -37,20 +37,13 @@ def monitor_memory():
3737

3838

3939
def main(show=True, local=True):
40-
# Create app
41-
app = create_app()
42-
4340
# Monitor potential memory leak
4441
monitor_memory()
4542

4643
# Serve the app
4744
print("Starting app...")
4845
if local:
4946
port = find_free_port(5003)
50-
pn.serve(app, port=port, show=show, title="Neuropixels Channelmap Generator", verbose=True)
47+
pn.serve(create_app, port=port, show=show, title="Neuropixels Channelmap Generator", verbose=True)
5148
else:
52-
app.servable(title="Neuropixels Channelmap Generator")
53-
54-
55-
if __name__ == "__main__":
56-
main(show=True, local=True)
49+
create_app().servable(title="Neuropixels Channelmap Generator")

channelmap_generator/gui/gui.py

Lines changed: 24 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -167,6 +167,27 @@ def __init__(self, **params):
167167
# Create widgets
168168
self.create_widgets()
169169

170+
# Register cleanup on session destroy
171+
if pn.state.curdoc:
172+
pn.state.curdoc.on_session_destroyed(self._cleanup_session)
173+
174+
def _cleanup_session(self, session_context):
175+
"""Clean up resources when session ends"""
176+
177+
self.clear_bokeh_data()
178+
179+
if hasattr(self, 'electrode_source'):
180+
del self.electrode_source
181+
if hasattr(self, 'tool_state_source'):
182+
del self.tool_state_source
183+
if hasattr(self, 'plot'):
184+
del self.plot
185+
if hasattr(self, 'plot_pane'):
186+
del self.plot_pane
187+
188+
gc.collect()
189+
print(f"🧹🧹🧹 Session {session_context.id} cleaned up")
190+
170191

171192
#####################################
172193
##### Probe geometry and wiring #####
@@ -493,9 +514,7 @@ def on_electrode_selection(self, _, old, new):
493514
# Clear the selection to allow for new interactions
494515
self.electrode_source.selected.indices = []
495516

496-
# Force garbage collection after large selections to free memory
497-
if len(new) > 100:
498-
gc.collect()
517+
gc.collect()
499518

500519

501520
def get_zigzag_subset(self):
@@ -676,10 +695,8 @@ def generate_pdf_content(self):
676695
buffer.seek(0)
677696

678697
finally:
679-
# Force cleanup of matplotlib resources
680-
plt.close('all') # Close all figures
681-
plt.clf() # Clear current figure
682-
plt.cla() # Clear current axes
698+
plt.close('all')
699+
gc.collect()
683700

684701
return buffer
685702

entrypoint.sh

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -18,4 +18,7 @@ exec uv run panel serve ./app.py \
1818
--port "$INTERNAL_PORT" \
1919
--allow-websocket-origin "$ALLOW_WEBSOCKET_ORIGIN" \
2020
--num-procs "$NUM_PROCS" \
21+
--session-token-expiration 3600000 \
22+
--check-unused-sessions 10000 \
23+
--unused-session-lifetime 60000 \
2124
--show

0 commit comments

Comments
 (0)