Quando usar Array, Buffer ou Buffer direto

Questão

Ao escrever uma classe Matrix para uso com bibliotecas OpenGL, me deparei com a questão de usar matrizes Java ou uma estratégia Buffer para armazenar os dados (JOGL oferece cópia direta de buffer para operações Matrix). Para analisar isso, escrevi um pequeno programa de teste de desempenho que compara as velocidades relativas de operações em loop e em massa em Arrays vs Buffers vs. Buffers diretos.

Eu gostaria de compartilhar meus resultados com você aqui (como eu os acho bastante interessantes). Por favor, sinta-se livre para comentar e / ou apontar quaisquer erros.
O código pode ser visto empastebin.com/is7UaiMV.

Notas

A matriz de leitura de loop é implementada comoA [i] = B [i] caso contrário, o otimizador JIT irá remover completamente esse código. Realvar = A [i] parece ser praticamente o mesmo.

No resultado de amostra para o tamanho de matriz de 10.000, é muito provável que o otimizador JIT tenha substituído o acesso de matriz em loop por uma implementação semelhante a System.arraycopy.

Não há buffer de buffer em massa -> como implementos JavaA.get (B) ComoB.put (A)Portanto, os resultados seriam os mesmos que os resultados em massa.

Conclusão

Em quase todas as situações, é altamente recomendável usar os arrays internos Java. Não só é a velocidade de colocar / obter massivamente mais rápida, o JIT também é capaz de realizar otimizações muito melhores no código final.

Buffers devem ser usado seambos aplica-se o seguinte:

Você precisa processargrandes quantidades De dados.Esses dados são principalmente ou sempreprocessado em massa.

Note que um backened-buffer tem um Java Array que suporta o conteúdo do buffer. Recomenda-se fazer operações neste back-buffer em vez de colocar / colocar em loop.

Buffers diretos devem ser usado se você se preocuparuso de memória e nunca acessar os dados subjacentes. Eles são um pouco mais lentos que os buffers não diretos, muito mais lentos se os dados subjacentes forem acessados, mas usam menos memória. Além disso, há uma sobrecarga extra ao converter dados não-byte (como float-arrays) em bytes ao usar um buffer direto.

Para mais detalhes, veja aqui:

Por que somente os ByteBuffers são úteis ao usar buffers diretosSobrecarga interna no NIO e o que diminui os buffersResultados da amostra

Nota: A porcentagem é apenas para facilitar a leitura e não tem significado real.

Usando matrizes de tamanho 16 com 10.000.000 iterações ...
-- Array tests: -----------------------------------------

Loop-write array:           87.29 ms  11,52%
Arrays.fill:                64.51 ms   8,51%
Loop-read array:            42.11 ms   5,56%
System.arraycopy:           47.25 ms   6,23%

-- Buffer tests: ----------------------------------------

Loop-put buffer:           603.71 ms  79,65%
Index-put buffer:          536.05 ms  70,72%
Bulk-put array->buffer:    105.43 ms  13,91%
Bulk-put buffer->buffer:    99.09 ms  13,07%

Bulk-put bufferD->buffer:   80.38 ms  10,60%
Loop-get buffer:           505.77 ms  66,73%
Index-get buffer:          562.84 ms  74,26%
Bulk-get buffer->array:    137.86 ms  18,19%

-- Direct buffer tests: ---------------------------------

Loop-put bufferD:          570.69 ms  75,29%
Index-put bufferD:         562.76 ms  74,25%
Bulk-put array->bufferD:   712.16 ms  93,96%
Bulk-put buffer->bufferD:   83.53 ms  11,02%

Bulk-put bufferD->bufferD: 118.00 ms  15,57%
Loop-get bufferD:          528.62 ms  69,74%
Index-get bufferD:         560.36 ms  73,93%
Bulk-get bufferD->array:   757.95 ms 100,00%
Usando arrays de tamanho 1.000 com 100.000 iterações ...
-- Array tests: -----------------------------------------

Loop-write array:           22.10 ms   6,21%
Arrays.fill:                10.37 ms   2,91%
Loop-read array:            81.12 ms  22,79%
System.arraycopy:           10.59 ms   2,97%

-- Buffer tests: ----------------------------------------

Loop-put buffer:           355.98 ms 100,00%
Index-put buffer:          353.80 ms  99,39%
Bulk-put array->buffer:     16.33 ms   4,59%
Bulk-put buffer->buffer:     5.40 ms   1,52%

Bulk-put bufferD->buffer:    4.95 ms   1,39%
Loop-get buffer:           299.95 ms  84,26%
Index-get buffer:          343.05 ms  96,37%
Bulk-get buffer->array:     15.94 ms   4,48%

-- Direct buffer tests: ---------------------------------

Loop-put bufferD:          355.11 ms  99,75%
Index-put bufferD:         348.63 ms  97,93%
Bulk-put array->bufferD:   190.86 ms  53,61%
Bulk-put buffer->bufferD:    5.60 ms   1,57%

Bulk-put bufferD->bufferD:   7.73 ms   2,17%
Loop-get bufferD:          344.10 ms  96,66%
Index-get bufferD:         333.03 ms  93,55%
Bulk-get bufferD->array:   190.12 ms  53,41%
Usando matrizes de tamanho 10.000 com 100.000 iterações ...
-- Array tests: -----------------------------------------

Loop-write array:          156.02 ms   4,37%
Arrays.fill:               109.06 ms   3,06%
Loop-read array:           300.45 ms   8,42%
System.arraycopy:          147.36 ms   4,13%

-- Buffer tests: ----------------------------------------

Loop-put buffer:          3385.94 ms  94,89%
Index-put buffer:         3568.43 ms 100,00%
Bulk-put array->buffer:    159.40 ms   4,47%
Bulk-put buffer->buffer:     5.31 ms   0,15%

Bulk-put bufferD->buffer:    6.61 ms   0,19%
Loop-get buffer:          2907.21 ms  81,47%
Index-get buffer:         3413.56 ms  95,66%
Bulk-get buffer->array:    177.31 ms   4,97%

-- Direct buffer tests: ---------------------------------

Loop-put bufferD:         3319.25 ms  93,02%
Index-put bufferD:        3538.16 ms  99,15%
Bulk-put array->bufferD:  1849.45 ms  51,83%
Bulk-put buffer->bufferD:    5.60 ms   0,16%

Bulk-put bufferD->bufferD:   7.63 ms   0,21%
Loop-get bufferD:         3227.26 ms  90,44%
Index-get bufferD:        3413.94 ms  95,67%
Bulk-get bufferD->array:  1848.24 ms  51,79%

questionAnswers(2)

yourAnswerToTheQuestion