2009-03-15 2 views
24

Se nella propria applicazione è presente un enumerazione e sono presenti solo alcuni elementi, è necessario forzare il tipo sottostante al tipo più piccolo possibile?Quando si dichiara un enum, si dovrebbe forzare il tipo a byte per meno di 256 entità?

enum smaller : byte 
    { 
     one, 
     two, 
     three 
    }; 
+2

Per essere chiari, stavo parlando delle migliori pratiche piuttosto che dell'ottimizzazione, anche se questa domanda si è presentata come una domanda di ottimizzazione. Il mio punto era proprio dal momento che puoi specificarlo, dovresti "sempre" specificare o dovresti o lasciare che il compilatore decidesse? – ghost

risposta

32

No. Non prematuramente ottimizzare a meno hai dimostrato con un profiler che in realtà è un problema.

+0

Penso che .NET sia ottimizzato affinché Enums diventi comunque. – Ray

+1

Per essere chiari, stavo parlando delle migliori pratiche piuttosto che dell'ottimizzazione, anche se questa domanda si è presentata come una domanda di ottimizzazione. Il mio punto era proprio dal momento che puoi specificarlo, dovresti "sempre" specificare o dovresti o lasciare che il compilatore decidesse? Immagino di lasciare come funziona per entrambi. – ghost

+2

come dimostreresti con un profiler se byte o int sono più efficienti? –

1

Cosa si otterrebbe? Avresti salvato ben 3 byte di memoria, a costo di un'esecuzione leggermente più lenta e di un codice meno intuitivo o leggibile. (Leggendo questo, devo chiedermi se Pyou avesse effettivamente un motivo per renderlo un byte e quale potesse essere stata questa ragione. Presumibilmente ti sei sforzato di usare un tipo non predefinito per una ragione).

Se si prevede di archiviare milioni di queste cose, allora sì, il salvataggio di alcuni byte su ciascuna potrebbe ripagare. Altrimenti no.

È lo stesso motivo per cui in genere non si utilizza byte o short anziché int.

0

Non si deve assegnare un determinato tipo intero alle enumerazioni ma lasciare che l'ambiente .NET calcoli la migliore "dimensione" per l'enumerazione. Come ha detto JaredPar, se si modifica il tipo di dati, si dovrebbe sicuramente verificare se effettivamente aiuta.

Il fatto è che gli interi a 32 bit sono "naturali" sui processori x86 perché possono essere facilmente allineati in modo ottimale.

26

relative alle migliori prassi:

quando non si dispone di un motivo particolare per la realizzazione del enum un tipo di byte, si dovrebbe lasciare come predefinito.

Ogni volta che si utilizza un enum in un'istruzione switch si dovrebbe avere una clausola "predefinita" per un valore enum non valido. Quindi non importa se stai verificando 256-NumRealEnumValues ​​o 2^32-NumRealEnumValues. Entrambi avranno una clausola predefinita che gestisce tutti i casi non validi.

Un motivo per impostare esplicitamente il tipo di enumerazione è se si desidera che l'enumerazione corrisponda a un altro tipo nel programma e che sia necessario eseguire il cast esplicito tra di essi.

Cambiare il tipo al più piccolo non ti aiuterà nemmeno con i problemi di versione. A meno che tu non abbia esattamente la dimensione massima dell'enumerazione. Per problemi di versione, intendo quando si ha una DLL compilata che utilizza l'enumerazione, si aggiunge un nuovo valore enum, potrebbe essere eseguito codice che non era destinato alla clausola "predefinita" di un'istruzione switch.

in materia di efficienza:

No, non c'è alcun beneficio in termini di efficienza per renderlo un byte.

int è più efficiente da utilizzare poiché la cpu su x86 ha registri a 32 bit. La copia in un registro viene eseguita a 32 bit alla volta.

Quando si utilizza un tipo più piccolo, è necessario azzerare parte del registro e copiare nel resto dei bit di ordine inferiore del registro.

+3

Stai pensando solo alle prestazioni della CPU. Mentre il costo per azzerare i bit di registro richiesti è praticamente trascurabile, i guadagni di efficienza nell'utilizzo della memoria possono essere notevoli. – 0b101010

+1

"può essere sostanziale" è tecnicamente vero, ma dubito che diventerà sostanziale molto spesso.Nella mia esperienza, i singoli byte (non negli array) sono spesso inseriti in un limite di parole, quindi molti byte occupano la stessa quantità di memoria di un int. – Luke

5

L'unica ragione per farlo è se si sta memorizzando o trasmettendo questo valore utilizzando un protocollo definito che richiede che il campo sia di tale dimensione.

+3

Non direi che è l'unica ragione. Lo faccio spesso perché ho bisogno di conservare centinaia di milioni di oggetti in memoria, e i tre byte per risparmio di dati sono abbastanza significativi. –

+0

@Jim: se nella memoria ci sono così tanti elementi, è più probabile che tu abbia un problema da qualche altra parte. Stai sacrificando le prestazioni per lo spazio. È necessario scambiare questi elementi dalla memoria o ottenere più memoria. – Juliano

+3

@Juliano Non penso che sia indicativo di un problema altrove. Nel mondo della negoziazione algoritmica in tempo reale è spesso necessario conservare milioni di elementi di dati (ad esempio transazioni, aggiornamenti di ordini) alla volta. La rasatura di 3 byte per elemento di dati produce un vantaggio significativo. – 0b101010

0

Se si sta mappando il modello con enum su un altro modello, o serializzandolo, o l'enum si riflette sulla colonna del database, quindi suggerisco di specificare il tipo in modo esplicito.


Scenario: Hai una colonna nel database: status_id con il tipo tinyint. E hai enum nel tuo codice: enum Status { Well = 1, Bad = 2 }. E tu usi questo enum in qualche entità. Supponiamo che tu usi i framework di entità core 2.0. Se provi a leggere/scrivere questa entità dal database, visualizzerai l'errore "Impossibile eseguire il cast dell'oggetto", a meno che non specifichi esplicitamente il tipo byte.