2013-03-09 7 views
5

E 'possibile in C# .Net (3.5 e versioni successive) copiare una variabile in un buffer byte [] senza creare alcuna spazzatura nel processo?C# Copia le variabili nel buffer senza creare garbage?

Ad esempio:

int variableToCopy = 9861; 

byte[] buffer = new byte[1024]; 
byte[] bytes = BitConverter.GetBytes(variableToCopy); 
Buffer.BlockCopy(bytes, 0, buffer, 0, 4); 

float anotherVariableToCopy = 6743897.6377f; 
bytes = BitConverter.GetBytes(anotherVariableToCopy); 
Buffer.BlockCopy(bytes, 0, buffer, 4, sizeof(float)); 

... 

crea l'oggetto intermedio byte [] bytes che diventa spazzatura (presumendo un ref non è più tenuto ad esso) ...

Chissà se utilizzando operatori bit per bit i la variabile può essere copiata direttamente nel buffer senza creare il byte intermedio []?

+0

Sì, è possibile, ma a me sembra che tu stia ottimizzando prematuramente. I rifiuti che crei in una chiamata al metodo, come piccoli array di byte e simili, sono tutti oggetti Gen 0 e verranno raccolti probabilmente in un paio di millisecondi o, probabilmente, anche meno. L'allocazione e raccolta temporanea di oggetti nel CLR è estremamente efficiente. – codekaizen

+0

Whare sono oggetti Gen 0? – markmnl

+0

(Per la tua preoccupazione - non penso che l'ottimizzazione sia prematura - non sono sicuro di come suonassi così - sto scrivendo una libreria che verrà usata dai telefoni e usando il buffer 100 forse un migliaio di volte un secondo - e il GC è una preoccupazione per tali dispositivi con risorse limitate). – markmnl

risposta

2

Utilizzare i puntatori è il migliore e il modo più veloce: Si può fai questo con un numero qualsiasi di variabili, non c'è memoria sprecata, l'istruzione fissa ha un piccolo sovraccarico ma è troppo piccola

 int v1 = 123; 
     float v2 = 253F; 
     byte[] buffer = new byte[1024]; 
     fixed (byte* pbuffer = buffer) 
     { 
      //v1 is stored on the first 4 bytes of the buffer: 
      byte* scan = pbuffer; 
      *(int*)(scan) = v1; 
      scan += 4; //4 bytes per int 

      //v2 is stored on the second 4 bytes of the buffer: 
      *(float*)(scan) = v2; 
      scan += 4; //4 bytes per float 
     } 
+0

Forse qualcosa da dire: prenditi cura di tutti gli oggetti fissi (fissi). Possono causare la frammentazione dell'heap che potrebbe finire con l'usare più memoria alla fine. – Caramiriel

1

Perché non puoi semplicemente fare:

byte[] buffer = BitConverter.GetBytes(variableToCopy); 

Si noti che la matrice qui non è un riferimento indiretto al deposito per l'originale Int32, è molto più di una copia.

Si sono forse preoccupati che bytes nel tuo esempio è equivalente a:

unsafe 
{ 
    byte* bytes = (byte*) &variableToCopy; 
} 

.. ma vi assicuro che non lo è; è una copia byte per byte dei byte nella sorgente Int32.

EDIT:

base alla tua modifica, penso che si desidera qualcosa di simile (richiede contesto non sicuro):

public unsafe static void CopyBytes(int value, byte[] destination, int offset) 
{ 
    if (destination == null) 
     throw new ArgumentNullException("destination"); 

    if (offset < 0 || (offset + sizeof(int) > destination.Length)) 
     throw new ArgumentOutOfRangeException("offset"); 

    fixed (byte* ptrToStart = destination) 
    { 
     *(int*)(ptrToStart + offset) = value; 
    } 
} 
+0

perché diversamente dal mio esempio il mio buffer deve contenere molte variabili - aggiornerò la mia domanda – markmnl

Problemi correlati