Loading obj and mtl files using the three.js OBJMTLLoader.js results in a memory leak when repeatedly loading them

I encountered a memory leak issue while loading multiple obj mesh files with mtl file using three.js. Here are the steps I followed:

Start by visiting this page: . Once the page is loaded, click on 'load' and you will see yellow meshes appearing on the screen as you move your mouse;

Next, if you are using Windows, open your task manager to check how much memory the browser tab is consuming, take note of it.

Lastly, click on 'reload', then re-click on 'load' at the top-left corner of the page or 'clear', and monitor the memory usage in the task manager again. You'll notice that the memory usage keeps increasing and doesn't seem to decrease.

I have included some release code at the end of the index.js file, here is the snippet:

function reload() {
    var indexes = [];
    for (var index in scene.children) {
        if(scene.children[index].name.indexOf('test') !== -1){
            indexes.push(scene.children[index]);
        }
    }
    for(var index in indexes){
        scene.remove(indexes[index]);
    }
    load();
};

I made changes to the two main functions as follows:

function load() {
    clear();
    var paths = [];
    for(var i=1;i<=4;i++){
        paths.push({obj: i + '/model_1v.obj', mtl: i + '/model_1v.mtl'});
    }

    var onProgress = function(xhr) {
        if (xhr.lengthComputable) {
            var percentComplete = xhr.loaded / xhr.total * 100;
        }
    };

    var onError = function(xhr) {};

    THREE.Loader.Handlers.add(/\.dds$/i, new THREE.DDSLoader());
    for(var i=0;i<paths.length;i++){
        var path = paths[i];
        var loader = new THREE.OBJMTLLoader();
        loader.load(path.obj, path.mtl, function(model) {
            model.name='test-' + i;
            scene.add(model);
        }, onProgress, onError);
    }
}

function clear() {
    THREE.Cache.clear();
    var models = [];
    for (var i in scene.children) {
        if(scene.children[i].name.indexOf('test') !== -1){
            models.push(scene.children[i]);
        }
    }
    for(var i in models){
        scene.remove(models[i]);
        models[i].traverse(
           function(obj){
                if (obj instanceof THREE.Mesh) {
                    obj.geometry.dispose();
                    obj.material.dispose();
                }
            }, true
        );
    }
    models.length = 0;
};

Despite these changes, the issue persists. If you're interested in helping out or exploring further, you can clone the code from this repository: https://github.com/idazhenhan/idazhenhan.github.io.git , and run the code on your local server to get a clearer picture of the problem.

I am seeking assistance in resolving this issue. Can anyone help me with this?

Answer №1

When it comes to the javascript garbage collector, all references to an object must be zero for it to kick in. A simple way to notify javascript that you are finished with an object is by setting it to undefined. Moreover, remember to dispose() all objects within a group. Below is my method of disposing a hierarchy.

After executing scene.remove(models[i]);

Implement either:

disposeHierarchy (object, disposeNode);
or disposeNode (node);

var debugging = false;
var indent = "", indent_level = 0;

function disposeNode (node)
{
    if (debugging) console.log (indent_level + " " + indent + "\"" + node.name + "\"");

         if (node instanceof THREE.Camera)
    {
        if (debugging) console.log (indent + "\"" + node.name + "\"" + " " + "\"" + node.type + "\"" + " Camera");

        node = undefined;
    }
    else if (node instanceof THREE.Light)
    {
        if (debugging) console.log (indent + "\"" + node.name + "\"" + " " + "\"" + node.type + "\"" + " Light");

        node.dispose ();
        node = undefined;
    }
    else if (node instanceof THREE.Mesh)
    {
        if (debugging) console.log (indent + "\"" + node.name + "\"" + " " + "\"" + node.type + "\"" + " Mesh");

        if (node.geometry)
        {
            if (debugging) console.log (indent + indent + "I have Geometry");

            node.geometry.dispose ();
            node.geometry = undefined;
        }

        // Similar code block continued...

        node = undefined;
    }
    else if (node instanceof THREE.Object3D)
    {
        if (debugging) console.log (indent + "\"" + node.name + "\"" + " " + "\"" + node.type + "\"" + " Object3D");

        node = undefined;
    }
    else
    {
        if (debugging) console.log (indent + "UNKNOWN " + "\"" + node.name + "\"" + " " + "\"" + typeof node + "\"");
    }
}

function disposeHierarchy (node, callback)
{
    indent += "    ";
    indent_level++;

    for (var i = node.children.length - 1; i >= 0; i--)
    {
        var child = node.children[i];
        disposeHierarchy (child, callback);
        callback (child);
    }

    indent = indent.substr (4); // remove 4 spaces from indent
    indent_level--;
}

Similar questions

If you have not found the answer to your question or you are interested in this topic, then look at other similar questions below or use the search

Is there a way to transfer a value from one JS function to another in Node.js?

I am struggling to retrieve the return value from a JavaScript function in Node.js and pass it back in a POST method within my server file. Despite my efforts, I keep receiving an undefined result. What could be causing this issue? My objective is to retur ...

Utilize NgRepeat to access an unidentified array in AngularJS

In a complex multi-level array, there are objects nested at the deepest level. [ [ [ "FUND", { "totassets":10.9, "totdate":"2015-03-23", "expratiogross":1.35, "exprationet" ...

Error: Module specifier "react-router-dom" could not be resolved. Relative references should start with either "/", "./", or "../"

I encountered an error message after executing the command npm run preview: Uncaught TypeError: Failed to resolve module specifier "react-router-dom". Relative references must start with either "/", "./", or "../". ...

What is the best way to retrieve the content from the MongoDB Document in my GET request?

I encountered an issue while attempting to access the Question field within the JSON document body stored in a MongoDB database. Upon executing the GET request, the result displayed as follows: { "_readableState": { "objectMode": true, "highWaterM ...

Is it possible to incorporate HTML and CSS into a npm package?

I've been searching extensively for an answer to this question, but haven't found a clear answer. I recently began using the node package manager and I'm wondering if it's possible to publish a package that includes HTML and CSS, or if ...

jshint Issue: Module 'underscore' Not Found

My grunt task is running smoothly, yet I keep encountering the following error every time: Loading "jshint.js" tasks...ERROR >> Error: Cannot find module 'underscore' Is there a way to determine the cause of this issue? The /grunt-contrib ...

What is the best way to check for changes in value using the onchange

The function is encountering an error and failing to execute. Despite my attempts to check for the onchange property in order to prevent errors, I keep receiving an error message stating "Cannot read property 'onchange' of undefined." Below i ...

"Transforming JSON data into structured key-value pairs using JavaScript

Develop a function named "json_filter" that accepts a JSON-formatted string as input. The accepted format is an array of objects, where each object contains keys for "mass," "density," "temperature," and "velocity," each mapped to a floating-point number. ...

Attempting to route a selector, yet on the second attempt, the entity is successfully transferred

I am currently working on developing a function that will switch the image every half second for 10 iterations. During the final iteration, the image src will be set to the actual value. Everything seems to work fine for the first loop, however, when the s ...

Error encountered with the OffsetWidth in the Jq.carousel program

I am encountering an issue that I cannot seem to figure out. Unexpected error: Cannot read property 'offsetWidth' of undefined To view the code in question, click on this link - http://jsfiddle.net/2EFsd/1/ var $carousel = $(' #carouse& ...

Redis Recursion: The callstack has reached its maximum size limit

Looking for some assistance with creating a game timer. I've decided to utilize Redis and Web Sockets in order to synchronize the timer across multiple devices. However, I'm running into an issue when trying to call my function recursively using ...

Vue.js: Utilizing async/await in Vue.js results in an observer being returned

Currently, I'm attempting to retrieve data from an API and store it in an array. The issue arises when I try to log the response data from the API - the data is displayed just fine. I assign the value of a variable to the data obtained from awaiting t ...

What is the best way to deactivate a button with an onclick function in javascript?

I would like to enhance the button click event behavior by disabling it after it has been clicked. How can I modify the function so that when the button is clicked, it becomes disabled and then redirects to the specified URL? <form id="edit" action=" ...

Failing to catch the return value from a stored procedure in ASP Classic

Apologies for the lengthy post, but I wanted to provide all the necessary details. I am facing an issue with a JavaScript function that uses ajax to call some asp code, which then executes a stored procedure to check if a record already exists. Depending ...

Hover shows no response

I'm having trouble with my hover effect. I want an element to only be visible when hovered over, but it's not working as expected. I've considered replacing the i tag with an a, and have also tried using both display: none and display: bloc ...

Creating a line of functions pool in Javascript with a delay feature

Recently, I created a code snippet that simulates a function line. It involves calling functions such as fn1, delay, fn2, delay, and so on. The idea is to call a function, remove it from the line, have a short sleep, and repeat. However, I've encount ...

Adjust the classes of the static navigation bar based on the background of the section it is positioned over

In the process of developing a website using Bootstrap 4, I encountered a challenge with sections featuring both light and dark backgrounds along with a fixed navbar. The navbar, which is set to dark using the css class bg-dark, becomes indistinguishable ...

Using jQuery or JavaScript, extract JSON data from Yahoo Pipes

Here is the JSON format that I receive from Yahoo pipes: {"count":3, "value":{ "title":"Freak count feed", "description":"Pipes Output", "link":"http:\/\/pipes.yahoo.com\/pipes\/pipe.info?_id=565sdf6as5d4fas ...

When using the .append method in jQuery, the JSON array only displays the last value of the array when iterating through it with

<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.0 Transitional//EN"> <html> <head> <title>Displaying Array Data in Table Using Javascript</title> <script src="http://ajax.googleapis.com/ajax/libs/jquery/1.11.1/jquery.min.js">& ...

Three.js - Exploring Camera Rotation and Transformations

I have a three.js scene where I can add and edit objects. Recently, I added a checkbox for "Rotate Camera" which is working well. However, the issue I am facing is that the transformControls attached to the object seem to rotate differently: when I stop th ...