High memory usage when displaying STLs with pyvista

Hi,

I am trying to set up some sort of a subjective experiment where I’ll ask some observers to compare various 3D objects (loaded as STL meshes).
I’m running the app locally, it all works (almost) fine, except that the memory usage keeps going up, and I end up with a segmentation fault (when too many volumes are loaded).
I’m not sure I quite understand streamlit’s caching mechanism, I’ve tried quite a few things, but I always end up with a memory crash.

My code looks like that (my apologies, it’s a bit long) :

import streamlit as st
import pyvista as pv
from stpyvista import stpyvista


st.set_page_config(layout="wide", initial_sidebar_state="collapsed")


cnt = st.session_state.count
#st.write(cnt)


#@st.cache_resource
def read_and_display_stl(plname):
	plotter = pv.Plotter(window_size=[320,320])

	mesh = pv.read(plname)
	mesh['myscalar'] = mesh.points[:, 2] * mesh.points[:, 0]

	## Add mesh to the plotter
	plotter.add_mesh(mesh, scalars='myscalar')

	plotter.view_isometric()
	plotter.background_color = 'gainsboro'

	return(plotter)


# Create side-by-side columns
col10, col20, col30 = st.columns(3)


if cnt < st.session_state.nb_im:
	with col20:

		plotter0 = read_and_display_stl(st.session_state.pl[cnt*4+1])

		## Send to streamlit
		stpyvista(plotter0, key=str(cnt))

	col1, col2, col3 = st.columns(3)


	with col1:

		plotter1 = read_and_display_stl(st.session_state.pl[cnt*4+2])

		## Send to streamlit
		stpyvista(plotter1, key=str(cnt+1))

		option1 = st.selectbox('Bifurcation # 1',
		['Choose a score',1,2,3], index = None, key='selection1')
		Score1=option1


	with col2:

		plotter2 = read_and_display_stl(st.session_state.pl[cnt*4+3])

		## Send to streamlit
		stpyvista(plotter2, key=str(cnt+2))

		option2 = st.selectbox('Bifurcation # 2',
		['Choose a score',1,2,3], index = None, key='selection2')
		Score2=option2


	with col3:

		plotter3 = read_and_display_stl(st.session_state.pl[cnt*4+4])

		## Send to streamlit
		stpyvista(plotter3, key=str(cnt+3))

		option3 = st.selectbox('Bifurcation # 3',
		['Choose a score',1,2,3], index = None, key='selection3')
		Score3=option3


st.markdown("""---""")


if cnt == st.session_state.nb_im:
	st.session_state.count = 0
	st.session_state.PL = []
	del st.session_state["count"]
	del st.session_state["pl"]
	st.switch_page("pages/end.py")



def update_counter():
	st.session_state.count += 1

	if (st.session_state.count >= 1):
		with open("./outputs/" + st.session_state.key + ".txt", "a") as myfile:
			myfile.write("%s\t%s\t%s\n" %(st.session_state.pl[(st.session_state.count-1)*4+2], 
												  st.session_state.pl[(st.session_state.count-1)*4+3], 
												  st.session_state.pl[(st.session_state.count-1)*4+4]))
			myfile.write("%s\t%s\t%s\n" %(Score1, Score2, Score3))
 

def reset_selectboxes():
	st.session_state.selection1 = 'Choose a score'
	st.session_state.selection2 = 'Choose a score'
	st.session_state.selection3 = 'Choose a score'


def master_callback():
	update_counter()
	#st.cache_data.clear()
	#st.cache_resource.clear()
	#read_and_display_stl.clear()
	reset_selectboxes()


runButton = st.button("Validate", on_click=master_callback)

Basically, the protocol is as follows: the observers will see 4 volumes displayed on the monitor, one on top, which is the reference, and three below, in a row that they’ll need to sort in resembling order (using a selectbox).

I’ve plotted the memory usage, and it seems the memory is never freed (see attached image).
Any help would be hugely appreciated, I’ve been struggling on this for a while now.

plot_orig

Best regards.
Florent

Would you see the same problem with memory if you instead used:

from stpyvista.trame_backend import stpyvista

after upgrading to version 0.1.0

pip install --upgrade stpyvista[trame]

If the goal is just to display STL files, how about not using pyvista at all and use this other component instead:

2 Likes

Hi @edsaac

Thanks a lot for you suggestions.
It seems that there’s still a monotonically increasing use of the memory, but it’s actually much better.
I end up having an overall lower memory consumption, if the “psrecord” plot is to be trusted (see below).

I will look into streamlit-stl, thanks for the tip.
I just hope the final rendering is as nice as the one provided by pyvista.

plot_trame_backend

Hi,

Just a quick follow up.
Unfortunately, despite the (much) better memory management when using the trame backend, this doesn’t quite work out for me, as now, each pyvista Plotter is refreshed (its position being reinitialized) when I select a score in the selectbox, this will be too cumbersome for the observers , as they will have to position each object all over again after each rating (not sure I make myself clear there… ?)

Moreover, I’ve also tried streamlit_stl, it looks quite promising, and extremely easy to use (haven’t checked the memory consumption though), but unfortunately, it is not yet as nice as the PyVista rendering, which looks really great (see screenshots showing successively streamlit_stl and pyvista below).

I keep investigating this memory issue, but I have to admit, I’m a bit lost there.
Any help would be greatly appreciated.

Best regards,
Florent

Hi @Florent1, try upgrading to stpyvista==0.1.2 and pass a key to your stpyvista instances. That should avoid the 3D view from remounting at every interaction. There is an example of that behavior in the demo app for stpyvista:


The trame backend was not implemented as a streamlit component, I was just passing the plotter directly to components.html , so every interaction in the app ended up refreshing the whole thing. That changed with version 0.1.2.

Thanks a lot @edsaac for taking the time to look into my problem(s).
The demo you’ve shared seems to be exactly what I need !
I did already pass a key to the stpyvista instances, hopefully, version 0.1.2 will fix my issues, but unfortunately, I am encountering an error when importing stpyvista== 0.1.2 , I end up with an:
ImportError: cannot import name 'Required' from 'typing'

any idea where that could come from ?

Yeah, that comes from running a version of Python < 3.11. You could upgrade to 3.11 while I publish a patch to fix address that. Would you mind opening an issue at GitHub - edsaac/stpyvista: 🧊 Show pyvista 3D visualizations in streamlit?

Wonderful !
I gave it a quick try, it seems to work just fine.
Thanks so much !
I’ve been stuck on this for quite a while. You’ve been really helpful.

Keep up with the great work, streamlit and pyvista are great.
(note: I’ve opened the issue on GitHub)

Thank you for doing the initial memory probing!

I fixed the original issue with the panel backend (some details at `stpyvista.panel_backend` allocates too much memory · Issue #29 · edsaac/stpyvista · GitHub) and it should not consume that much memory with the changes included in stpyvista==0.1.4. The gallery app even runs more smoothly after the changes (:

That’s very cool !
I’m glad I could be helpful (quite unintentionally though !)

This topic was automatically closed 180 days after the last reply. New replies are no longer allowed.