-
Notifications
You must be signed in to change notification settings - Fork 70
Description
Hi,
I'm using the itk-vtk-viewer in my react app as a component on one page, and it receives live frames from websocket and then display it by setImage(image,"live-frame"). But the browser can crash if the live viewer stayed for around 5 minutes. I notice the memory and CPU usage kept going on frame received. I've tried to use setInterval to set new random images on interval to confirm the memory leak was not caused by websocket, and I tried to pass viewer.getImage("live-frame") to viewer.setImage, and this doesn't cause memory leak either. My guess is each time I pass in the new image as ndarray, which will trigger the toMultiscaleSpatialImage to call itkImageToInMemoryMultiscaleSpatialImage, and this class might somehow cache the previous frames? Or the reference to the previous image is somehow still captured somewhere?
The related code snippet is as below
import "itk-vtk-viewer";
const Monitoring = () => {
const decodeArrayBuffer = (buffer) => {
// Get a dataview of the arraybuffer
const view = new DataView(buffer);
// Extract the size of the json encoded header
// as a 32bit int in pos 0 of the blob (little endian)
const header_size = view.getUint32(0, true);
// Create two new ArrayBuffers for the header and image
// by slicing the original at the appropriate positions
const header_bytes = buffer.slice(4, header_size + 4);
const image_bytes = buffer.slice(header_size + 4);
// Decode the header bytestream into a string and then
// parse into a JSON object
const decoder = new TextDecoder("utf-8");
// TODO: Figure out why this requires so many parsings!
const header_json = JSON.parse(
JSON.parse(JSON.stringify(decoder.decode(header_bytes)))
);
// Return a dictionary with the header and image
return { header: header_json, image: image_bytes };
};
const [viewer, setViewer] = React.useState(null);
const liveFrameViewer = useRef(null);
var intervalId = setInterval(function() {
console.log("NOTE Interval reached every 5s");
viewer?.setImage(
encodeArray(ndarray(new Uint16Array(2560 * 2160).map(
() => Math.random() * 1000
), [ 2560,2160])),"live-frame"
);
// the below code doesn't cause memory leak
//viewer?.setImage(
// viewer.getImage("live-frame"),"live-frame"
// );
}, 5000);
useEffect(() => {
if (liveFrameViewer.current) {
console.log("NOTE create viewer")
itkVtkViewer
.createViewer(liveFrameViewer.current, {
image: encodeArray(ndarray(defaultImageData, [1024, 1024])),
use2D: true,
imageName:"live-frame",
})
.then((viewer) => {
viewer.setImageColorMap('X Ray',0);
setViewer(viewer);
});
}
}, [liveFrameViewer]);
return (
<Box sx={{ width: "100%", height: "100%", minHeight: "1000px" }}>
<Grid
id="live-viewer"
ref={liveFrameViewer}
sx={{
position: "relative",
width: "100%",
height: "70%",
flex: "1 1 auto",
p:3,
m:3
}}
></Grid>
</Box>
);
}