2012-02-12 8 views
6

Attualmente sto leggendo di Oreilly Learning XNA 4.0 e ho notato che l'autore è incline alla creazione di un valore struct, come ad esempio Vector2 o Rectangle più volte senza alcun riguardo per le prestazioni.Prestazioni di creare struct valori

Ad esempio, un metodo SquareCollision(), che controlla la collisione tra due entità gioco crea due Rectangle s ogni volta che viene chiamato, invece di dover ogni entità gioco reggere il Rectangle campo e confronta i campi senza creare più struct valori.

Ho visto questo schema molte volte in molti luoghi e questo mi ha fatto meravigliare:
La creazione di valori di struct è trascurabile in C#?
Questo è veramente nella sezione delle micro-ottimizzazioni?

Forse perché la mia esperienza è per lo più con Java, il concetto di ValueType s è strano per me, ma sembra che ricreare un valore da una struttura (e chiamando è costruttore) più volte sembra uno spreco enorme di risorse.

+2

Hai provato a profilarlo? –

+0

Penso che sia un po 'difficile da profilare, perché quello che conta davvero è il successo generale delle prestazioni. Anche se ricreare lo stesso valore è 10.000 volte più lento rispetto all'utilizzo di un campo, significherebbe comunque poco se si riscontra solo un impatto dello 0,0001% sulle prestazioni. (Ci scusiamo per i numeri arbitrari, solo cercando di farmi capire.) Quello che sto cercando di capire è quanto sia pessima una pratica (se non del tutto) e se dovrei o non provare a evitarlo. – Acidic

+1

Potresti rendere la domanda un po 'più concreta mostrando il codice. Previene incomprensioni. –

risposta

6

La creazione di una struttura per un breve utilizzo nello stack è molto economica e non è molto diversa dalla semplice impostazione di variabili locali per tutti questi valori, ma con la componentizzazione. Tuttavia, come parte dell'oggetto sarebbe un ulteriore duplicato degli stessi dati per oggetto.

Entrambi gli approcci sono validi, a seconda dello scenario. In pila, tuttavia, non vi è alcun costo reale delle risorse. Come parte di un oggetto, dovresti assicurarti di non duplicare i dati inutilmente, poiché ciò avrebbe un costo effettivo.

Se si trattasse di una proprietà su un oggetto, è necessario copiarlo molte volte.

Se si tratta di un campo su un oggetto, sì: potrebbe essere utilizzato sul posto senza mai copiare, ma: questo è relativamente piccolo nella maggior parte dei casi.

Come sempre, è necessario il profilo per sapere se è importante.

+0

Mi sembra che l'unica via d'uscita sia usare campi ** protetti/pubblici ** per assicurarsi che la stessa struttura sia sempre usata, invece di essere duplicata inutilmente. O forse un metodo che riceve le strutture per riferimento usando la parola chiave ref? – Acidic

+0

@Acidic se si utilizza la struct ** direttamente ** (non assegnando a una variabile, ecc.), Quindi non ha bisogno di una copia; ma sì - i metodi che accettano le strutture tramite "ref" sono abbastanza comuni in questo scenario. Uso questo approccio io stesso in alcuni posti pazzi ottimizzati. –

1

La cosa che non ha alcun vantaggio per l'oggetto Mesh all'interno dell'oggetto (per esempio), in pratica. Causa al momento della richiesta, il valore della struttura sarà copiato. Si consideri ad esempio:

public class Mesh 
{ 
    public Vector3 MeshCogVector {get;set}; 
} 

e in qualche parte del codice che avere

public void CollisionDetection 
{ 
    for(int i=0;....) 
    { 
     Mesh curmesh = listofmashes[i]; 
     Vector3 vec3 = curmesh.MeshCogVector; //value copied 

    } 
} 

Quindi, utilizzando in questo modo nelle vostre condizioni, che, fondamentalmente, non si ottiene alcun beneficio + si aumenta la dimensione Mesh esempio.

Invece di utilizzare/costruire quell'istanza Vector3 all'interno del metodo effettivo, nel momento in cui ne hai effettivamente bisogno, si ottiene rapidamente l'allocazione dello stack e la rapida garbage collection.

Se non si è soddisfatti delle prestazioni nelle strutture, è possibile considerare l'utilizzo degli array di dati non safe. Ma questo è qualcosa che dovresti misurare, per capire se questo è lo scenario adatto a te.

+0

non sarebbe risolto se utilizzo semplicemente un campo pubblico invece di una proprietà pubblica? A quanto ho capito, le proprietà struct creano una nuova copia della struct sulla chiamata getter. – Acidic

+0

@Acidic: no, non cambierebbe nulla. Non si tratta del parametro di accesso proprietà/campo/funzione di ritorno, si tratta dei [tipi di valore C#] (http://msdn.microsoft.com/en-us/library/s1ax56ch.aspx). Puoi ** provare **, se vuoi tenere un 'Vector' all'interno della classe, per passarlo con la parola chiave ref 'le funzioni come' CollisionDetection'. In questo caso, il valore non verrà copiato, ma passato ** per riferimento **. Ma è qualcosa, ancora una volta, che devi misurare. Vorrei andare, se la classe 'Vector' non è grande, per la soluzione che hai già visto, in modo da allocare nel momento in cui è necessario. – Tigran

+0

Odio porre domande del genere, ma cosa è * grande *? Un 'Vector2' potrebbe non essere grande, ma per quanto riguarda' Vector4' o 'Rectangle'? Immagino che * * si possa rispondere solo con la profilazione ... – Acidic

Problemi correlati