Blazor wasm huge memory leak because of graphic library - please help

Javier 1 Reputation point
2020-12-05T17:58:19.403+00:00

Hi,

First time here, thanks for giving the chance to ask tech questions directly !
I have an enterprise project (Blazor wasm) that needs to display several components (think each a different navigation page). Two of them need to display different graphic models (one is a graph, like in graph theory and the other is a model of pipes and connectors). I have used threejs, babylonjs in the past inside Blazor wasm, but I decided to go with pixijs this time because its high performance and how easy it is to make interactive 2D models on it (click, drag and drop, etc). I need to use user interaction. The models are super simple: graphic shapes like rectangles, circles, and just 1 texture (reused across). A Sprite to provide drag and drop functionality.

Unfortunately, I am getting a huge memory leak that goes from 200MB (Blazor app just loaded) to 4GB in a matter or minutes :-(( I thought that the leak came from Blazor repainting the components each time, so I did an override on the method that prevents repainting these 2 components.
I tried keeping only one instance of the javascript variable that holds an entire 2D application in my index.html page for the entire lifetime. Then, I read that doing this might not be a good idea, so I create the graphical application every time instead (each component would make a JSInterop call to an init() method to create and draw).
In order to make this happen, I have a DIV element in each of those 2 components and I bind my graphic models on that DIV (via a getElementById and setting the content to the view of the 2D app).
Everything happens in Javascript universe via JSInterop. For the cleanup of shapes and textures, I tried to subscribe to the event when the blazor component is "navigated away" (nav.LocationChanged). In that handler I would then call a cleanup() method via JSInterop. I would of course unregister (-=) the LocationChanged handler on Dispose() to avoid any leaks with those 2 "sensitive" components.

Are there any good practices in how to deal with javascript graphic libraries in Blazor wasm that need to create a component containing a graphical model over and over ? Most of the examples use a single component. In my case the user can go from one model to another, and it is this go back and forth that starts to consume the entire memory in a matter of minutes :((( Even if I do go to one model, then request another component and then back again over and over, I experience the leak.
I now know that the leak is not coming from Blazor wasm per se, but I would like to know if there are any good practices (like not adding a DIV (that will contain a canvas in the end, via WebGL). RIght now I do not even have a DIV to draw on, because the js library will create one (document.body.appendChild(app.view);

If I cannot fix this huge leak, I am ready to flush everything and try to use another graphical library. This is how desperate I am :((
Can you guys suggest me a native Blazor libray that uses WebGL natively (not Canvas) ? (hopefully not even using JS interop at all !!). I have seen Wave Engine, but I understand it is not 100% ready for web usage ?

I apologize for the super long post ! I can try to run a simple "dotnet new blazorwasm" and make a demo to reproduce the problem and upload it in a repo somewhere, to see if any of you can take a look and guide me better with the best practice for this particular use case !
Thanks in advance and best regards

Javier

Blazor
Blazor
A free and open-source web framework that enables developers to create web apps using C# and HTML being developed by Microsoft.
1,389 questions
{count} votes