Serving images at 10 FPS will keep increasing RAM. Even when the sessions are closed and stopped the RAM does only partially clean up. There is no upper bound, it keeps increasing over time. This will eventually lead to problems, especially on SBC with limited RAM. After running in multiple tabs, I am hitting 16GB RAM allready after about 10 minutes. Please not that having all sessions closed will not reduce RAM usage. It will stay steady at the last amount of RAM used, and after opening new sessions it will start climbing again.
Steps to reproduce
import numpy as np
import streamlit as st
img = np.random.rand(600,600,3)
# Get current date and time
img_with_date = img.copy()
now = datetime.datetime.now()
dt_string = now.strftime("%d/%m/%Y %H:%M:%S.%f")[:-3]
cv2.putText(img_with_date, dt_string, (10, 30), cv2.FONT_HERSHEY_SIMPLEX, 1, (0, 0, 0), 2)
if "page_open" not in st.session_state:
st.session_state.page_open = True
if "num_img" not in st.session_state:
st.session_state.num_img = 0
st.title("Test memory usage of st.image...")
text_placeholder = st.empty()
img_placeholder = st.empty()
while "page_open" in st.session_state:
st.session_state.num_img += 1
if __name__ == "__main__":
Just run this app for a while, in multiple browser tabs will take up memory quicker. Then close them, stop the last app, clear the cache. then check the memory.
I don’t know what the expected behavior would be from Streamltis perspective, but in my use case each image will ever be served once to each session. I want Streamlit to clean up these resources as soon as possible.
The behavior I am getting is that more and more RAM is being consumed over time. It does not increase anymore once all sessions are closed (using Streamlit 1.17.0 for that reason because 1.18+ keeps sessions open way longer than it should).
If you would run this code on Streamlit 1.18+ it would not terminate the sessions based on the session state condition, and it will lead to undesirable results.
Closing all sessions will keep the RAM usages approximately the same. Will update the post to better reflect that. If I let it climb up to 16 gigabytes of RAM usage and all sessions are closed it still uses 16 gigabytes of ram.
@vdonato we discussed things on Github about the detection of closed sessions. Before I create an issue about this topic I want to ask if you see anything going wrong here? The sample I posted will just keep using more RAM (not when there are no sessions) but the RAM usage never goes down. Only stabilizes without open sessions but otherwise it keeps increasing.
So even when this issue gets resolved I am still not able to keep a single session open for longer than a few hours before I run out of memory. Are there some advanced settings to control image caching in RAM or am I just doing something wrong here?
Memory not being cleaned up for a single very-long-lived session isn’t too surprising to me – I believe the refs to the images generated during a script run currently won’t be cleaned up until script execution has finished, so the garbage collector won’t reclaim the memory until after the script execution completes.
You could likely muck around with some Streamlit internals (in particular by calling methods defined in media_file_manager.py) to get this cleanup to happen more frequently. We can’t guarantee the stability of the APIs of internal modules, but my unofficial opinion is that it’s highly unlikely that MediaFileManager’s will change any time soon. Happy to help find a workaround using this method if I happen to have more time later this week, but I currently don’t have too much bandwidth.
I am surprised that memory isn’t being reclaimed even after a session ends, though. Please feel free to file a new GitHub issue for this and tag me in it if you have a consistent repro.