My app has many plotly charts. The problem is, whenever I change an input that controls one chart, all the other charts are also redrawn. This can be quite slow, even if I cache the functions that produce the plotly figures. I guess “st.plotly_chart” still has to translate the plotly figure to web elements, and that takes time. Is there anyway around this? Thanks!
Steps to reproduce
Code snippet:
import streamlit as st
import plotly.express as px
import pandas as pd
@st.experimental_memo
def load_data():
# US births 2014, from an R data set repo
return pd.read_csv('https://vincentarelbundock.github.io/Rdatasets/csv/openintro/births14.csv')
@st.experimental_memo
def figure(df_in, facet_in='marital'):
return px.scatter(df_in, x='gained', y='weight', color='habit', facet_col=facet_in)
df = load_data()
st.header('Test chart redraw')
st.plotly_chart(figure(df))
st.plotly_chart(figure(df))
st.plotly_chart(figure(df))
st.plotly_chart(figure(df))
st.plotly_chart(figure(df))
st.plotly_chart(figure(df))
st.plotly_chart(figure(df))
st.plotly_chart(figure(df))
st.plotly_chart(figure(df))
st.plotly_chart(figure(df))
st.plotly_chart(figure(df))
facet = st.radio('facet', ['marital', 'sex', 'whitemom'])
st.plotly_chart(figure(df, facet))
Scroll to the bottom of the page
Change the radio button.
Note how all the charts are redrawn, even though the radio button should only affect the last chart.
Expected behavior:
Only the last chart is redrawn and updated.
Actual behavior:
The affected chart is slow to update, because streamlit redraws all the charts above it first, even though those figures haven’t changed.
Note: if this doesn’t happen on your computer, then just add more charts until you see the delay. (And be thankful that you have a fast computer )
Hi @HHest, would you be willing to add a line to your streamlit app
st.write(st.__version__) just to triple-check that you’re actually running the app with 1.14.0?
There was a bug that was recently fixed which should keep plotly charts for re-rendering unnecessarily.
I tried your code, but with 100 plotly charts, on streamlit 1.14.0, and didn’t see any visible delay or redrawing of other charts when manipulating one the charts. This made me wonder if you might actually be running the app with a different version of streamlit.
Thanks for replying, @blackary. I got “1.14.0” when I did that, and the lag behavior is still there. I got the same behavior on the Edge browser, too.
(I took a screencast, but this website doesn’t support WEBM, which is a bit unfortunate since streamlit itself uses WEBM.)
… Have used an online converter to get a WEBP file. Caveat emptor…
… Well, that didn’t work, but we have the screenshot anyway…
… Got it working with an animated gif. It’s not as clear, but still you can see the “Running” images appear and the graphs fading in and out. (This is with 11 graphs above the final graph.)
I apologize, @HHest – I did not read your instructions very carefully about when you were seeing the bug. I am now seeing exactly the behavior you described.
The bad news is that this is simply the default behavior of streamlit – when one input is changed, it reruns the whole app. Normally you solve issues like this by using st.experimental_memo to cache slow parts of your app’s code (e.g. fetching data). And, st.experimental_memo has recently been updated so that you actually can cache charts like this, but in my experimentation it didn’t seem to add much performance benefit (presumably actually rendering all those charts on the screen, even if they are pre-cached, is still slow).
So, I’m stumped to find a better way. The good news is, that bug fix I mentioned probably means it’s a lot faster than it used to be, but I’m not sure how you can avoid a visible re-render with a large number of charts in your app.
I see. Thanks for confirming this issue, @blackary.
My actual situation is worse than the example because of the complexity of my own graphs.
One thing I’ve tried is to group graphs under different tabs, but unfortunately Streamlit would draw the contents of the tabs even if they are not active. It would have helped if Streamlit would check and run only the code inside the active tab. (Codes to render tabs are clearly isolated in their “with” contexts, so I am hoping this is possible?)
Eventually though, one might still run into a situation where the complexity of the graphs on the same page would cause this lag issue to appear.
Honestly, I love Streamlit for its simplicity, but this limitation is giving me pause. It seems costly to redraw everything every time any input is changed, and at some point that cost will catch up to you.
You can use radio buttons or a selectbox instead of tabs, so that only the code related to the selected option will run. If you want radio buttons that look like tabs, or tabs that behave like radio buttons, you are not the first one. There are some components that might help with that (I didn’t use any of them so I don’t really know).
Wanted to upvote this. Having the same issue (just with two graphs, so nothing so tragic luckily). It seems like this is a somewhat blocking issue for some use cases. I imagine there isn’t a super easy dev fix, but it seems you could make headway if tabs rendered separately from each other.
Thanks for stopping by! We use cookies to help us understand how you interact with our website.
By clicking “Accept all”, you consent to our use of cookies. For more information, please see our privacy policy.
Cookie settings
Strictly necessary cookies
These cookies are necessary for the website to function and cannot be switched off. They are usually only set in response to actions made by you which amount to a request for services, such as setting your privacy preferences, logging in or filling in forms.
Performance cookies
These cookies allow us to count visits and traffic sources so we can measure and improve the performance of our site. They help us understand how visitors move around the site and which pages are most frequently visited.
Functional cookies
These cookies are used to record your choices and settings, maintain your preferences over time and recognize you when you return to our website. These cookies help us to personalize our content for you and remember your preferences.
Targeting cookies
These cookies may be deployed to our site by our advertising partners to build a profile of your interest and provide you with content that is relevant to you, including showing you relevant ads on other websites.