Domanda

Qual è il layout di memoria di un array .NET?

Prendi ad esempio questo array:

Int32[] x = new Int32[10];

Comprendo che la maggior parte dell'array è così:

0000111122223333444455556666777788889999

Dove ogni carattere è un byte e le cifre corrispondono agli indici nell'array.

Inoltre, so che esiste un riferimento al tipo e un indice di sincronizzazione per tutti gli oggetti, quindi quanto sopra può essere adattato a questo:

ttttssss0000111122223333444455556666777788889999
        ^
        +- object reference points here

Inoltre, la lunghezza dell'array deve essere memorizzata, quindi forse questo è più corretto:

ttttssssllll0000111122223333444455556666777788889999
        ^
        +- object reference points here

È completo? Ci sono più dati in un array?

La ragione per cui sto chiedendo è che stiamo provando a stimare quanta memoria prenderà un paio di diverse rappresentazioni in memoria di un corpus di dati piuttosto grande e la dimensione delle matrici varia un po ', quindi l'overhead potrebbe avere un grande impatto in una soluzione, ma forse non tanto nell'altra.

Quindi, fondamentalmente, per un array, quanto sovraccarico c'è, questa è sostanzialmente la mia domanda.

E prima che la matrici siano cattive la squadra si risveglia, questa parte della soluzione è un tipo di cosa statica build-once-reference-spesso, quindi qui non è necessario usare liste coltivabili.

È stato utile?

Soluzione

Ottima domanda. Ho trovato questo articolo che contiene diagrammi a blocchi sia per i tipi di valore che per i tipi di riferimento. Vedi anche questo in cui Ritcher afferma:

  

[snip] ogni array ha qualche ulteriore   informazioni generali associate a   esso. Questa informazione contiene il grado   dell'array (numero di dimensioni),   i limiti inferiori per ogni dimensione di   l'array (quasi sempre 0) e il   lunghezza di ogni dimensione. Il sovraccarico   contiene anche il tipo di ciascun elemento   nella matrice.

Altri suggerimenti

Un modo per esaminarlo è guardare il codice in WinDbg. Quindi, dato il codice qui sotto, vediamo come appare nell'heap.

var numbers = new Int32[] { 0, 1, 2, 3, 4, 5, 6, 7, 8, 9 };

La prima cosa da fare è individuare l'istanza. Dato che l'ho reso locale in Main(), è facile trovare l'indirizzo dell'istanza.

Dall'indirizzo possiamo scaricare l'istanza effettiva, che ci dà:

0:000> !do 0x0141ffc0
Name: System.Int32[]
MethodTable: 01309584
EEClass: 01309510
Size: 52(0x34) bytes
Array: Rank 1, Number of elements 10, Type Int32
Element Type: System.Int32
Fields:
None

Questo ci dice che è il nostro array Int32 con 10 elementi e una dimensione totale di 52 byte.

Dump della memoria in cui si trova l'istanza.

0:000> d 0x0141ffc0
0141ffc0 [84 95 30 01 0a 00 00 00-00 00 00 00 01 00 00 00  ..0.............
0141ffd0  02 00 00 00 03 00 00 00-04 00 00 00 05 00 00 00  ................
0141ffe0  06 00 00 00 07 00 00 00-08 00 00 00 09 00 00 00  ................
0141fff0  00 00 00 00]a0 20 40 03-00 00 00 00 00 00 00 00  ..... @.........
01420000  00 00 00 00 00 00 00 00-00 00 00 00 00 00 00 00  ................
01420010  10 6d 99 00 00 00 00 00-00 00 01 40 50 f7 3d 03  .m.........@P.=.
01420020  03 00 00 00 08 00 00 00-00 01 00 00 00 00 00 00  ................
01420030  1c 24 40 03 00 00 00 00-00 00 00 00 00 00 00 00  .$@.............

Ho inserito parentesi per i 52 byte.

  • I primi quattro byte sono il riferimento alla tabella dei metodi a 01309584.
  • Quindi quattro byte per la lunghezza dell'array.
  • Di seguito sono riportati i numeri da 0 a 9 (ciascuno di quattro byte).
  • Gli ultimi quattro byte sono nulli. Non ne sono del tutto sicuro, ma suppongo che debba essere il punto in cui è memorizzato il riferimento all'array syncblock se l'istanza viene utilizzata per il blocco.

Modifica: lunghezza dimenticata nel primo post.

L'elenco è leggermente errato perché, come indica Romkyns, l'istanza inizia effettivamente all'indirizzo - 4 e il primo campo è il Syncblock.

Ottima domanda! Volevo vederlo da solo, e mi è sembrata una buona opportunità per provare CorDbg.exe ...

Sembra che per le matrici intere semplici, il formato sia:

ssssllll000011112222....nnnn0000

dove s è il blocco di sincronizzazione, l la lunghezza dell'array e quindi i singoli elementi. Sembra che alla fine ci sia uno 0, non sono sicuro del perché.

Per array multidimensionali:

ssssttttl1l1l2l2????????
    000011112222....nnnn000011112222....nnnn....000011112222....nnnn0000

dove s è il blocco di sincronizzazione, t il numero totale di elementi, l1 la lunghezza della prima dimensione, l2 la lunghezza della seconda dimensione, quindi due zero?, seguito da tutti gli elementi in sequenza, e infine di nuovo uno zero .

Gli array di oggetti vengono trattati come array di numeri interi, i contenuti sono riferimenti questa volta. Le matrici frastagliate sono matrici di oggetti in cui i riferimenti puntano ad altre matrici.

Un oggetto array dovrebbe memorizzare quante dimensioni ha e la lunghezza di ogni dimensione. Quindi c'è almeno un altro elemento di dati da aggiungere al tuo modello

Autorizzato sotto: CC-BY-SA insieme a attribuzione
Non affiliato a StackOverflow
scroll top