Va bene riutilizzare un'istanza di classe?

0

Chiedo in termini di classi di costo elevato, con un motore di particelle come esempio.

Ho letto da qualche parte che un'istanza di una classe con un costo elevato da inizializzare, come un gestore di particelle, dovrebbe avere le sue variabili di stato alterate in fase di esecuzione piuttosto che reinizializzare il gestore di particelle con nuovi dati ogni volta che viene utilizzato in un altro modo.

Il gestore di particelle creerebbe forse migliaia di istanze di particelle durante l'inizializzazione e poi le gestirà da quel momento in poi.

Per esempio, diciamo che questo gestore di particelle è usato per gestire le schegge in un'esplosione; e stai creando una simulazione ground zero per un attacco di artiglieria; quindi ci sono molte esplosioni.

Invece di più gestori per ogni esplosione, che è estremamente costoso, si alterano le variabili per ogni esplosione e si ha un insieme sequenziale di esplosioni sparpagliate usando lo stesso gestore e le stesse particelle.

Quindi chiedo: è bello riutilizzare un'istanza di classe in fase di esecuzione? O il precedente è solo un caso di super ottimizzazione?

    
posta user2738698 09.04.2014 - 17:22
fonte

2 risposte

5

È perfettamente utile riutilizzare un oggetto come questo purché sia scritto correttamente a tale scopo.

Il richiamo del comportamento sull'oggetto non dovrebbe essere influenzato da alcuna chiamata precedente all'oggetto. Considera il seguente codice:

class Example {
  private int x = 1;

  public int multiply(int y) {
    return x *= y;
  }
}

La chiamata alla funzione multiply() modifica lo stato della classe. Chiamarlo più volte produce risultati diversi, quindi per produrre risultati coerenti occorrono più oggetti. Certo, questo è un esempio forzato ma mostra il problema: questa classe non è facilmente riutilizzabile da due processi diversi.

Potrebbe anche essere permissibile avere un modo per resettare un oggetto. Forse ha requisiti di archiviazione complessi ed è più rapido azzerarne lo spazio di archiviazione che rilasciare e riacquistare risorse. Questo è un semplice esempio di Java che mostra cosa intendo:

List<Object> data = new ArrayList<Object>(1000000);
someMethod(data);
data.clear();
someMethod2(data);

Mentre ArrayList non è un oggetto molto costoso, pensa a un milione di elementi. Forse è più veloce azzerarlo piuttosto che chiedere al gestore della memoria di trovare un altro blocco di memoria che possa ospitare tale quantità di memoria (e Java azzererà comunque la memoria, rendendo clear() più veloce in questo caso).

Sfortunatamente non c'è modo di dire con certezza che funzionerà o meno, tutto ciò che possiamo fare è dire "se il codice lo fa, funzionerà o meno".

    
risposta data 09.04.2014 - 17:47
fonte
0

Supponendo che l'utilizzo precedente sia completato e che non si verifichi il paralelismo:

Dipende dal costo (sia di runtime che di sviluppo) di far diventare l'istanza "neutrale". A volte è più facile eliminare (o non fare più riferimento e lasciare a rilasciare per GC) l'intero oggetto che ispezionare ed eliminare le sue parti. E a volte è difficile essere sicuri di averlo fatto bene. E a volte l'autore originale non ha mai usato il riutilizzo, quindi alcune operazioni sono solo a senso unico. E il riutilizzo dell'oggetto può (nei sistemi con GC) portare a essere spostato su una generazione più lunga, quindi anche se non è necessario subito dopo sarà GCed molto più tardi (se è necessario, allora non importa).

Questo non significa che non dovresti mai farlo, basti pensare alle conseguenze e misurare il risultato.

Se stai progettando un oggetto di questo tipo, prova a dividerlo in oggetti costosi riutilizzabili (non contenenti stato dall'uso) e nel modo più economico possibile oggetto di utilizzo non riutilizzabile. (ad esempio in ibernazione c'è la fabbrica Session (costosa) e crea una sessione (relativamente economica).

    
risposta data 09.04.2014 - 17:52
fonte

Leggi altre domande sui tag