Proof that GLTFLoader does not free memory in Safari that it frees in Chrome

You need to loop through every entity and use every dispose function of every entity’s descendents that have a dispose function first in reverse order then once an entity has no descendents, remove it from the parent and complete the rest of the equal tier entities while doing that to each parent.

There is a function that you can find with Google that claims to do that and does it out of order.

There’s always a CPU instruction count argument that is valid of speed when entities are never given known descendents with regards to a repeatable function and the term dispose is already required by sub-entities in THREE.js regarding a known command that can be used per entity (there entity is to be understood as a mesh, and groups that are entities contain meshes).

Andrew

@andrewhodel
No. The critical issue isn’t what you can do, but what you can’t do: your topic suggests a loader does not release memory on a specific platform. I suggest you can do several known strategies to release memory (which is private or complex to access). To reiterate: production code (such as a todo list… or 60fps spa which constructs optimal GLTFs on innumerous platforms) may implement brutish logic to release the tended memory.

Despite whether this outlines your motivation to apply a mitigation strategy or not… this is a multivarious concept to hit a multifaceted moving target. Even if GC is immediate, your app performance may assume an imbalanced profile. Theoretically, if a todo app architecture were virtualized on Mac Safari emulating a PC Chrome… would you reverse-engineer the solution of nondeterministic timestamps in the loaf of bread?

I think the usage of analogies isn’t without consideration of self defense.

Regardless of the applicable analogies, there’s also a blatent disregard of property.

It seems in the specific context however, the easiest solution would be to ask for a function or set of functions.

I think the systems of salary and the systems of redundant companies already solve what the analogies are trying to dissuade or fear.

I think evolution is probable, I don’t know why @lpassini wouldn’t want to improve.

Specifically, “or 60fps spa which constructs optimal GLTFs on innumerous platforms) may implement brutish logic to release the tended memory.” doesn’t consider the truth of a bad ruler no longer wanting power but the optimal GLTF’s won’t ever care about how they are treated on the sidewalk because they aren’t the displays.

am i having a stroke

1 Like

@andrewhodel are you implying that Safari should be passed an array to better internally allocate a memory pool to batch process models streamed at 60fps?

EDIT: refined Firefox by distinguishing Safari

You’re not, trying to sound cryptic and edgy, while actually saying nothing at all is apparently groovy…

@lpassini

In a recent use case I found that releasing bit map image memory eased the issue significantly when working with many glb’s across many seperate scenes, however, assets will need to be completely reloaded if wanting to reference them again at a later point.

Here’s a full dispose method code snippet which can be used in a traverse or callback loop, the condition and suggestion in question being…

if (map.image && typeof map.image.close === ‘function’) { map.image.close();}

const disposeNode = (node) => {

    const disposeMap = (map) => {
        if (!map) return;

        if (map.image && typeof map.image.close === 'function') {
            map.image.close(); // clean bitmap memory
        }

        map.dispose();
    };

    const disposeMaterial = (material) => {
        if (!material) return;

        const materials = Array.isArray(material) ? material : [material];

        materials.forEach((mat) => {
            disposeMap(mat.map);
            disposeMap(mat.lightMap);
            disposeMap(mat.bumpMap);
            disposeMap(mat.normalMap);
            disposeMap(mat.specularMap);
            disposeMap(mat.envMap);
            disposeMap(mat.alphaMap);
            disposeMap(mat.aoMap);
            disposeMap(mat.displacementMap);
            disposeMap(mat.emissiveMap);
            disposeMap(mat.gradientMap);
            disposeMap(mat.metalnessMap);
            disposeMap(mat.roughnessMap);

            mat.dispose();
        });
    };

    if (node.isMesh) {
        if (node.geometry) {
            node.geometry.dispose();
        }

        if (node.material) {
            disposeMaterial(node.material);
        }
    } else if (node.isMaterial) {
        disposeMaterial(node);
    }
};

Let me know if this helps.

5 Likes

Thanks @Lawrence3DPK we are experimenting with better resource disposal and we are going to use your solution and try if it works better!

We’ll update here when we have more tests.

Thanks!

1 Like

if you wanted to do this in a loop for all children of a Scene or Object3D (instead of traversing a Scene or Object3D graph) you could use a pattern similar to the following…

const disposeHierarchy = (node) => {

    if(node.children?.length){

        for (let i = node.children.length - 1; i >= 0; i--) {
            let child = node.children[i];
            disposeHierarchy (child);
            disposeNode (child);
        }
    }
    else{
        disposeNode (node);
    }
}

Although this is roughly the pattern Object3D.traverse uses internally…

1 Like

You should certainly use your solution.

Glad you got it working.

I’ve been working with WebGL for more than 10 years and I literally don’t understand a single thing in this thread. Can someone translate this to a more peasant friendly English?

1 Like

Modern operating systems keep track of available memory and allocate space for various things (models, sounds, etc.). When the program ends or you tell the system to delete something, the operating system should automatically un-allocate that space, marking it as free space.

When I first started programming on the Apple ][+ (using assembly language), there were certain designated memory areas that you could use to store your programs. I then got an Amiga and tried using the same approach, only to learn that this was not good practice since you might overwrite another program. Instead, I learned to work with the memory management system that kept track of free space and allowed your program to be written into that free space.

Equally importantly, when you exited the program, the system would free the space. But that did not always happen. I had a few cases where the system did not free the memory and after running the program a few times, the system would tell your that there was no space available. You could see this happening by checking free memory before and after you ran the program. And you would see that free memory kept decreasing. This is called a “memory leak” and is what is being discussed here.

I hope that helps.

So, when they close safari, memory is not released and eventually the operating system crashes?

I’m guessing that’s practically impossible as safari’s vram memory limit is around 200-400mb depending on the device, which should be far less than the operating system’s memory limit / devices memory?

1 Like

It’s really bad that you guys cannot solve that at line 28 only one entity is being removed.

It’s probably your broad analogy base with the terming argument between entities and attributes, while attributes are still entities that don’t have parents.

The thing is, you’ve already forgotten the difference of multiple solutions being available and multiple solutions not being available.

@Lawrence3DPK already gave you a function to remove a mesh (disposeNode) and then a function that operates recursively (disposeHierarchy) that you can easily use to test in your own product or solution.

The first definition of solution isn’t a material in the English language.

That’s normal work with complex structures, working interleaved with other projects. Every good project manager knows not to harp on the same song 365 days in a row.

+1 here same

I am not 100% sure if it could happen every time you close a program during a Safari session or when you finally close Safari itself. I am guessing that it is the former.

Back in the Amiga days (40 years ago - yikes!!!), memory leaks could eventually cause memory to be used up. But as Lawrence3DPK pointed out that is unlikely today