Using cache with dataframes and "static st commands"

Summary

I’m following up on an announcement from release v1.12, which states… functions cached with st.experimental_memo or st.experimental_singleton can now contain static st commands. This allows caching text, charts, dataframes, and more!

Prior to v1.12, I used @st.experimental_memo to cache dataframes results. And I believe it worked as expected. However, I would like to understand how v1.12 improves performance and/or more specifically how I can cache charts to improve performance. Here’s an example to use for discussion:

Steps to reproduce

Code snippet:

import pandas as pd
import streamlit as st

df = pd.DataFrame({'a':[2,2], 'b': [3,4]})

@st.experimental_memo()
def cfunc(df):
    print('not cached')

st.button('Run function', on_click=cfunc, args=(df,))

Clicking the button only prints ā€œnot cachedā€ to the console once–which is the actual / expected behavior pre-v1.12.

If I modify the code with an st.write command as follows:

import pandas as pd
import streamlit as st

df = pd.DataFrame({'a':[2,2], 'b': [3,4]})

st.header('Page Title')

@st.experimental_memo()
def cfunc(df):
    st.write('not cached')
    print('not cached')

st.button('Run function', on_click=cfunc, args=(df,))

st.write('not cached') writes to the page every time I click the button, but print('not cached') still only prints to the console once.

So I’m wondering

Is this what was meant by ā€œcached functions can now contain static st commandsā€? Are there other applications of this upgraded version that I’m missing? Elaboration here would help me maximize the UX of my data app. Thanks.

Using a static st command within a cached function previously meant that the st command would only execute on a cache miss. As you noticed, in version 1.12.0, the static st command executes on every run rather than only on a cache miss.