2016-06-11 25 views
11

Qual è il modo corretto di rimuovere la scena della forma della mesh? In questo esempio:TRE js rimozione di oggetti dalla scena (ancora riservati in HEAP)

removable_items = []; 
    box = new THREE.Object3D(); 
    scene.add(box); 

    function add() { 
     var mesh = new THREE.Mesh(new THREE.IcosahedronGeometry(10, 5), new THREE.MeshPhongMaterial({color: 0xFFFFFF})); 
     box.add(mesh); 
     removable_items.push(mesh); 
     //clean(); ///// when is integrated in function memory is cleaned properly 
    } 

    function clean() { 
      if(removable_items.length > 0) { 
      removable_items.forEach(function(v,i) { 
       v.parent.remove(v); 
      }); 
      removable_items = null; 
      removable_items = []; 
      } 
    } 

    function makeExperiment(r) { 
     var i = 0; 
     while (i < r) { 
     add(); 
     i++; 
     if(r === i) console.log(r+' finnished '); 
     } 
    } 

makeExperiment(50); 

/// dopo che i mannualy impostato clean();

maglie non sono visibili in scena più, come previsto, ma davanzale utilizzando la memoria, che dopo un certo tempo di rivestimento con perdita di memoria e crash del browser.

Dov'è il problema, THREE.js ha fatto altri riferimenti?

Three.js R73

EDIT: quando è clean(); integrato in funzione (commentata ora nel codice) memoria viene pulita correttamente. Ma quando ho impostato clean(); manualmente dopo che makeExperiment(); è terminato, la memoria non è impostata come libera.

+0

sto guardando questo - che programma/strumento si usa per guardare la memoria? – dcromley

+0

La tua dichiarazione 'new THREE.IcosahedronGeometry (1, 5)' Il 2 ° parametro è dettaglio. Avere come 5 rende un sacco di elaborazione. È quella parte del tuo problema a cui vuoi rispondere? L'impostazione predefinita è 1. – dcromley

+0

Im che utilizza la mesh di dettaglio elevata per motivo, per illustrare chiaramente l'esempio di memoria. È lo stesso problema con i modelli JSON o OBJ, o la geometria della scatola, è sufficiente ripetere la funzione makeExperiment più a lungo. Sto usando la console chrome e l'istantanea della memoria di Chrome. – Martin

risposta

15

Ho fatto alcuni esperimenti e io penso non c'è niente di veramente sbagliato nel codice. Una cosa che ho imparato, però, è che quel garbage collector potrebbe non funzionare esattamente quando pensi che lo faccia. Nel caso in cui, ho avvolto il codice in un IIFE (buona pratica ma non necessario in questo caso) e mi aspettavo che l'heap venisse cancellato non appena la funzione finisse di funzionare e uscisse dall'ambito. Ma in realtà voluto del tempo affinchè eliminino:

clean 50

Così ho pensato, okey, thats non bene, che cosa se stavo creando più oggetti in quel periodo in cui il garbage collector è solo persistente, in modo ho fatto:

. 
. 
makeExperiment(50); 
clean(); 
makeExperiment(50); 
clean(); 
makeExperiment(50); 
clean(); 
makeExperiment(50); 
clean(); 
makeExperiment(50); 
clean(); 
makeExperiment(50); 
clean(); 
makeExperiment(50); 
clean(); 
makeExperiment(50); 
clean(); 

e questo è ciò che è accaduto:

clean 400

L'immondizia c sembra che ollector stia facendo il suo lavoro e tu li stia cancellando correttamente per questo scopo. Tuttavia,, probabilmente stai usando anche THREE.js Renderer, e se ho capito bene, il Renderer mantiene riferimenti a materiali, geometrie e trame. Quindi, se questi non vengono smaltiti correttamente, non saranno raccolti. THREE.js ha un metodo per Geometry s, Material s e Texture s chiamato .dispose() che notificherà al Renderer di rimuoverlo. Quindi questo è come vorrei cambiare il vostro clean() funzione:

removable_items.forEach(function(v,i) { 
    v.material.dispose(); 
    v.geometry.dispose(); 
    box.remove(v); 
}); 
+0

ciao e grazie!come vedo nel tuo grafico, la rimozione lascia ancora i dati in heap, quando faccio questo esperimento migliaia di volte, causerà il browser non risponde. Sto usando questa situazione nel gioco, e c'è un enorme bisogno di ricaricare nuovi oggetti (nemici) e rimuovere quelli vecchi - morti. Hai provato con la funzione clean() integrata nella funzione add()? (linea commentata nel mio codice) o hai eseguito clean() manualmente dopo un po 'di tempo? – Martin

+1

@Martin Ho provato a pulire all'interno della funzione 'add()' e manualmente dopo 'makeExperiment()' (come visto sopra). Non puoi controllare esattamente quando il garbage collector del browser deciderà di pulire, se vuoi che qualche variabile sia deselezionata, tutto ciò che puoi fare è rimuovere tutti i riferimenti. Quando si chiama 'clean()' dentro 'add()' il garbage collector non ha ancora pulito l'heap 50 volte, solo circa 6 volte, quindi era lo stesso comportamento. Il motivo per cui il browser non risponde è perché javascript è a thread singolo e si sta utilizzando quel thread per fare qualcosa 1000 volte. prova a dividerlo su più fotogrammi – micnil