2009-12-28 18 views
14

Poiché le strutture sono tipi di valori, i loro dati sono copiati quando passati in un metodo come argomento. Esempio:Le strutture sono "più veloci" delle Classi - In generale o nel framework .NET?

int someInt = 7; 

DoSomeMethod(someInt); // <-- This is passing the "value" 7. 

Finora, facile da capire, e probabilmente stai chiedendo come la mia domanda è valida ... in modo da considerare il seguente:

public struct TimmysStructOfGoodness 
{ 
    public int SomeInt1; 
    public int SomeInt2; 
    public int SomeInt3; 
    // ... later that day ... 
    public int SomeInt999; 
} 

e poi, con riferimento alla seguente codice:

TimmysStructOfGoodness someStructOfGoodness = new blah blah blah... 

DoSomeMethod(someStructOfGoodness); // <-- **HERE IS WHERE THE QUESTION APPLIES!** 

Condivide la dichiarazione di cui sopra cercano di allocare diversi mega di ram di "copiare" il mio valore-tipo (struct)?

Se la risposta è sì - poi quando/dove è il confine tra "più veloce" e "lento"?

Se no, allora perché no? Perché quello che so dei tipi di valore, questo dovrebbe essere un problema.

ESCLUSIONE PRINCIPALE: So che questo non ha nulla a che fare con il perché si dovrebbe usare una struct verses una classe, e so che non creerò mai una struct con i campi 999 - questa è solo una questione di interni e budella sottostanti e simili :)

+2

Da quando 999 int occupare diversi mega di RAM? :-) –

+0

La tua 'struct' sarebbe circa 4k, non" parecchi meg ". –

+3

Sapevo che qualcuno (qualcuno) stava per dirlo ... ma lo lasciò intenzionalmente. Ho pensato che tutti sappiano cosa sto dicendo. –

risposta

10

(aggiornato, grazie al contributo di altri utenti)

A differenza di classe, viene creato sul struct pila. Quindi, è più veloce istanziare (e distruggere) una struttura rispetto a una classe.

A meno che (come rilevato da Adam Robinson) struct sia un membro della classe, nel qual caso viene allocato in heap, insieme a tutto il resto.

D'altra parte, ogni volta che si assegna una struttura o la si passa a una funzione, questa viene copiata.

Non penso ci sia un limite rigido per una dimensione della struttura. Migliaia di byte sono decisamente troppi. MSDN says:

A meno che non hai bisogno di semantica tipo di riferimento, una classe che è più piccolo di 16 byte può essere più efficiente gestita dal sistema come una struct.

Questo è - se è necessario passarlo per riferimento, renderlo una classe, indipendentemente dalle dimensioni.

Al secondo pensiero, è comunque possibile passare struct per riferimento semplicemente specificando ref nell'elenco dei parametri delle funzioni.

Quindi, una struttura di grandi dimensioni può effettivamente essere ok se la si passa per riferimento e si usa come membro della classe.

+0

Preventivo molto bello (e informativo)! –

+6

Questo non è del tutto accurato ... le strutture locali sono dichiarate in pila; qualsiasi variabile di istanza (o variabile statica) sarà ancora dichiarata nell'heap, proprio come qualsiasi altra istanza o membro statico. –

+1

Mentre ci sono molte buone risposte, questa è probabilmente la "migliore" in quanto hai incluso il riferimento "16 byte" da MSDN - che è probabilmente la cosa più vicina alla chiusura che posso sperare di trovare in questa domanda . –

9

Strutture ed classi non hanno solo prestazioni diverse, si comportano in modo diverso anche. Dovresti usare quello che è più adatto al tipo che stai implementando. Le linee guida su quando utilizzare l'una o l'altra sono clearly described on MSDN. Utilizzare una struct solo se tutte le seguenti condizioni:

  • Esso rappresenta logicamente un singolo valore, simili ai tipi primitivi (integer, doppia, e così via).
  • Ha una dimensione dell'istanza inferiore a 16 byte.
  • È immutabile.
  • Non dovrà essere inserito frequentemente in una scatola.

Se si passa una struttura a una funzione, ne verrà fornita una copia. Se la tua struct è grande allora risulterà nella copia di molti dati. Un riferimento viene in genere implementato come 4 byte (su x86), quindi passare un oggetto richiede solo la copia di questi 4 byte.

Si noti inoltre che le linee guida precedenti richiedono che le strutture siano piccole.

+3

-1. Mentre le informazioni sono corrette, ha dichiarato esplicitamente di non * parlare * (né di interessarsi) dei diversi casi d'uso per struct vs. class. –

+0

Ben affermato, ma vedi il commento sopra di Adam. –

+1

Vale la pena addentrarsi: è possibile passare una struct per ref/out e non ne risulta una copia. Puoi anche inscatolare una struct sull'heap, nel qual caso, ancora nessuna copia. Il modo in cui si utilizzano le strutture e le si passano intorno agli impatti in cui sono allocati e in che modo vengono copiati. Anche una struttura dichiarata membro di una classe, ad esempio, non è allocata nello stack, ma nell'heap. – LBushkin

2

La risposta alla tua domanda è: Sì. Quando si definisce una struttura, ogni assegnazione comporta un'operazione di copia.

non c'è linea esatta che separa "fast" da "lento" perché ci sono molti fattori che influenzano WRT velocità per le strutture, quali:

<correzione> Structs vengono memorizzati per valore: sulla lo stack o all'interno degli oggetti contenenti. In tal modo promuovono la localizzazione della cache, poiché è probabile che la pagina pertinente sia già caricata nella cache della CPU dove è probabile che le pagine heap arbitrarie non lo siano. </correzione > Inoltre, le strutture non consentono l'override del metodo, quindi anche la spedizione del metodo è (marginalmente) più veloce.

D'altra parte, ogni incarico comporta una copia.Quindi se il tuo codice ha molti incarichi, i vantaggi di cui sopra saranno superati dal costo delle operazioni di copia. Il punto di pareggio è diverso da un programma all'altro (a causa di diverse caratteristiche di cache località, metodo di dispacciamento e le assegnazioni)

+2

Mentre ho fatto l'upvoting, questo deve essere chiarito/corretto. Solo le strutture locali saranno dichiarate in pila; qualsiasi istanza o struttura statica, come con tutti gli altri membri dell'istanza/statici, deve essere dichiarata nell'heap. –

+0

Giusto per essere chiari, ricorda che puoi sempre passare la struttura all'altro metodo per riferimento, evitando la copia se non hai bisogno di una copia. –

+0

@Adam: hai ragione. Corretto. –

6

Le implicazioni di prestazioni delle strutture dipendono esattamente da come si utilizzano tali strutture.

È impossibile fare una dichiarazione categoriale sul fatto che le strutture siano più veloci o più lente dei tipi di riferimento. Tutto dipende da come li usi e in quale contesto.

Le strutture (tipi di valori in generale) possono finire allocate nello stack o nell'heap, a seconda del loro contesto di dichiarazione. Se lo dichiari nel corpo di un metodo (e non lo inserisci esplicitamente), la struttura finirà nello stack. Se quindi si passa quella struct a un metodo che lo accetta in base al valore (come nell'esempio), verrà effettivamente copiato, ma in pila. L'allocazione nello stack è un processo molto efficiente (BTW, anche l'heap .NET è molto efficiente), ma è un processo di copia.

È possibile, naturalmente, passare la struttura utilizzando ref/out - in tal caso non si verificherà alcuna copia - verrà passato al metodo un riferimento alla struttura. Questo potrebbe, o no, essere desiderabile, poiché permetterà al metodo chiamato di cambiare il contenuto della struttura.

Una struttura dichiarata come membro di una classe verrà effettivamente allocata nell'heap (come parte del layout di memoria della classe). Se passi quella lezione in giro, la struttura non verrà copiata, ma sarà comunque accessibile attraverso il riferimento alla classe.

È inoltre possibile ottenere una struttura sul mucchio da boxe esplicitamente:

object x = new MyStruct(...); // boxed on the heap 

Jon Skeet ha una buona article about where things end up in memory che si dovrebbe leggere.

3

Per aumentare la confusione, ricorda, se non hai bisogno di una copia passato al altro metodo, si può sempre passare lo struct con riferimento ad evitare di fare una copia ...

+0

ooh, buon punto :) –

Problemi correlati