Skip to main content

🧠 Memory

Introduction#

πŸš€πŸš€ You have both freedom and responsibility when it comes to memory management in your IFC.js app. Fortunately, IFC.js lets you balance these to release memory very easily. Let's see how it's done. πŸ‘‡

πŸ—‘οΈ IFC.js builds upon the Three.js dispose() function. See how IFC.js does it here and here, and also read what Three.js has to say. πŸ—‘οΈ

How to do it#

Monitoring the memory#

πŸ‘€ stats.js is a library to monitor the memory and performance of your Three.js app, made by the creator of Three.js himself. Let's go ahead and install with npm i stats.js, import, initialize and attach it to our viewer.

import Stats from "stats.js/src/Stats";
const stats = new Stats();
addStats();
function addStats() {
stats.showPanel(2);
document.body.append(stats.dom);
viewer.context.stats = stats;
};

πŸ“‹ During development we don't have to second guess our memory management anymore, because now it's visualized for us.

Load up the model#

β›½β›½ First we'll create an HTML input button and use loadIfc() to load our models from file. 🎨 Style as you wish!

<input type="file" id="input-button" />
async function loadIfcFromFile(file) {
const model = await viewer.IFC.loadIfc(file, true);
}

πŸ‘οΈβ€πŸ—¨οΈ We call loadIfc() when a user loads an IFC file. Internally, it creates a URL then calls loadIfcUrl() for us.

πŸ’… Now link the button and the function.

const input_button = document.getElementById("input-button");
input_button.addEventListener("input", (input) => {
loadIfcFromFile(input.target.files[0])},
false
);

So that we can load and release the same model over and over, for this example we'll add a tiny hack to reset the DOM event.

input_button.addEventListener("click", (e) => {
e.target.value = "";
});

Dispose memory#

✌πŸ₯€ Finally let's create our function to dispose memory on command using dispose(). Here's how it's done:

function releaseMemory() {
viewer.dispose();
viewer = null;
viewer = new IfcViewerAPI({ container });
viewer.IFC.setWasmPath("../../../");
addStats();
}

❗❗ Keep in mind: Once we call dispose(), we need to re-initialize our viewer instance (and Stats module)❗❗

⌨️ For this example let's attach our function to a new HTML button.

<input type="button" id="release-button" value="Release Memory" />
const release_button = document.getElementById("release-button");
release_button.addEventListener("click", () => releaseMemory());

πŸ§ͺ Try loading a model and releasing the memory: you'll notice our model disappears and our visualizer confirms this. Remember that it might take time for the garbage collector to do its job.

The result#

😎 This is how the application looks like:

Github repo

Next steps#

πŸŽ‰πŸŽ‰πŸŽ‰ Congratulations! Your IFC.js apps are now free of memory leaks. This memory management will keep your app squeaky clean and running smooth. πŸ’ͺπŸ’ͺπŸ’ͺ