@st.cache_data memory growth across reruns: choosing eviction settings to keep RSS stable
0 reputation · 23 Aug 2021, 15:09 UTC
0 reputation · 23 Aug 2021, 15:09 UTC
I am designing a Streamlit app (version 1.18 or later) that uses @st.cache_data to cache large DataFrames returned from a data-loading function. Widget interactions rerun the script with varying filter parameters, so each distinct parameter combination creates a new cache entry. The goal is to keep the server process memory footprint bounded over long uptimes without excessive recomputation.
From the documentation, cached values persist for the lifetime of the server process unless evicted by ttl or max_entries, and st.cache_data.clear() releases entries programmatically. What is unclear is how to size these knobs: an aggressive TTL bounds memory but increases reload latency, while max_entries evicts by recency, which may thrash if users cycle among many parameter sets. There is also ambiguity about how server-wide cache memory interacts with per-session st.session_state objects holding derived data, since they have different lifecycles, and whether figures created inside cached functions need explicit closing to avoid additional retention.
max_entries or a moderate ttl the more predictable way to bound RSS, and how should the two be combined?st.cache_data.clear() on a schedule a reasonable safety net, or does it risk evicting entries other concurrent sessions still need?35275 reputation · 23 Aug 2021, 21:07 UTC
For a workload that can generate many distinct cache keys, max_entries is the most reliable knob to bound RSS. It guarantees that no more than the configured number of DataFrames are kept in memory, regardless of how long each one lives. A moderate ttl can be layered on top to drop entries that are unlikely to be reused after a user’s session ends, but it does not provide a hard limit.
max_entries to a value that, when multiplied by the average DataFrame size, stays below your RSS budget.ttl (e.g., 300–600 s) so that stale entries from abandoned sessions are evicted sooner, keeping the cache lean when users cycle through many filters.st.cache_data.get_cache_info() to confirm the entry count and a rough size estimate; adjust max_entries until info.current_entries matches your target.st.cache_data.get_cache_info() before and after a rerun to isolate cache memory from st.session_state memory. session_state lives in a separate dictionary and is not affected by cache eviction.plt.close(fig)) to avoid extra retention.st.cache_data.clear() removes all cached entries globally. This is safe only if you can guarantee that no active session still needs the data. In multi‑user deployments it risks evicting data required by concurrent users; prefer per‑session isolation or rely on max_entries and ttl instead.If you can provide the average size (in MB) of the DataFrames you cache and the RSS budget you need to stay within, I can give a more precise max_entries recommendation.
Use comments to ask for clarification. Post a solution as an answer.
No question comments on this page.