Pergunta

O que é o layout de memória de uma matriz .NET?

Tome por exemplo, essa matriz:

Int32[] x = new Int32[10];

Eu entendo que a maior parte da matriz é assim:

0000111122223333444455556666777788889999

Onde cada personagem é um byte, e os dígitos corresponde a índices na matriz.

Além disso, eu sei que há um tipo de referência, e uma syncblock-índice para todos os objetos, de modo que o acima pode ser ajustado a esta:

ttttssss0000111122223333444455556666777788889999
        ^
        +- object reference points here

Além disso, o comprimento da matriz precisa ser armazenado, então talvez esta seja mais correto:

ttttssssllll0000111122223333444455556666777788889999
        ^
        +- object reference points here

É este o completo? Há mais dados em uma matriz?

A razão que eu estou pedindo é que estamos tentando estimar quanta memória um par de diferentes representações na memória de uma bastante grande corpus de dados levará eo tamanho das matrizes varia um pouco, de modo que a sobrecarga pode ter um grande impacto em uma única solução, mas talvez não tanto na outra.

Então, basicamente, para um array, o quanto a sobrecarga está lá, que é basicamente a minha pergunta.

E antes que o matrizes são ruins esquadrão acorda, esta parte da solução é um acúmulo estático outrora-frequentemente referência tipo de coisa tão usando listas growable não é necessário aqui.

Foi útil?

Solução

Ótima pergunta. Eu encontrei este artigo que contém diagramas de blocos de dois tipos de valor e tipos de referência. Veja também este href="https://web.archive.org/web/20150110150255/http://msdn.microsoft.com/en-us/magazine/cc301755.aspx" rel="nofollow noreferrer"> artigo em que os estados Ritcher:

[recorte] cada matriz tem alguns adicional informações sobrecarga associada isto. Esta informação contém o posto da matriz (número de dimensões), os limites inferiores para cada dimensão de a matriz (quase sempre 0), e o comprimento de cada dimensão. a sobrecarga também contém o tipo de cada elemento na matriz.

Outras dicas

Uma maneira de examinar esta é olhar para o código no WinDbg. Assim, dado o código abaixo, vamos ver como que aparece no heap.

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

A primeira coisa a fazer é localizar a instância. Como eu fiz isso um local em Main(), é fácil de encontrar o endereço da instância.

A partir do endereço que pode despejar a instância real, o que nos 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

Isto diz-nos que é a nossa gama Int32 com 10 elementos e um tamanho total de 52 bytes.

Vamos despejo da memória onde a instância está localizado.

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  .$@.............

Eu tenho inserido suportes para os 52 bytes.

  • Os quatro primeiros bytes são a referência à tabela do método no 01309584.
  • Em seguida, quatro bytes para o comprimento da matriz.
  • sequência que são os números de 0 a 9 (cada um quatro bytes).
  • Os últimos quatro bytes são nulos. Eu não estou totalmente certo, mas eu acho que deve ser onde a referência para a matriz syncblock é armazenado se a instância é usado para o bloqueio.

Edit:. Comprimento Esqueceu na primeira postagem

A listagem é ligeiramente incorreta porque como pontos romkyns fora a instância realmente começa no endereço - 4 e o primeiro campo é o Syncblock.

Ótima pergunta! Eu queria ver por mim mesmo, e parecia uma boa oportunidade para experimentar CorDbg.exe ...

Parece que para arrays de inteiros simples, o formato é:

ssssllll000011112222....nnnn0000

, onde s é o bloco de sincronização, l o comprimento da matriz, e em seguida, os elementos individuais. Parece que há uma finalmente 0, no final, eu não sei por que isso é.

Para arrays multidimensionais:

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

, onde s é o bloco de sincronização, t o número total de elementos, L1 o comprimento da primeira dimensão, l2 o comprimento da segunda dimensão, em seguida, dois zeros ?, seguido por todos os elementos sequencialmente, e, finalmente, um zero novamente .

matrizes de objectos são tratados como a matriz de números inteiros, os conteúdos são referências neste momento. matrizes irregulares são arrays de objetos, onde as referências apontam para outras matrizes.

Um objeto de matriz teria que armazenar quantas dimensões que tem e o comprimento de cada dimensão. Portanto, há pelo menos mais um elemento de dados para adicionar ao seu modelo

scroll top