Cuándo usar Array, Buffer o Direct Buffer

Pregunta

Mientras escribía una clase de Matrix para usar con las bibliotecas de OpenGL, me encontré con la pregunta de si usar arreglos de Java o una estrategia de Buffer para almacenar los datos (JOGL ofrece una copia directa de buffer para las operaciones de Matrix). Para analizar esto, escribí un pequeño programa de prueba de rendimiento que compara las velocidades relativas de las operaciones en bucle y en masa en Arrays vs Buffers versus direct Buffers.

Me gustaría compartir mis resultados con ustedes aquí (ya que los encuentro bastante interesantes). Por favor, siéntase libre de comentar y / o señalar cualquier error.
El código se puede ver enpastebin.com/is7UaiMV.

Notas

La matriz de lectura en bucle se implementa comoA [i] = B [i] de lo contrario, el optimizador JIT eliminará completamente ese código. Realvar = A [i] Parece ser más o menos lo mismo.

En el resultado de muestra para un tamaño de matriz de 10,000, es muy probable que el optimizador JIT haya reemplazado el acceso de matriz en bucle con una implementación similar a System.arraycopy.

No hay un buffer de obtención masiva-> buffer como implementos de JavaA.get (B) comoB.put (A), por lo tanto, los resultados serían los mismos que los resultados de venta masiva.

Conclusión

En casi todas las situaciones, se recomienda encarecidamente utilizar las matrices internas de Java. No solo la velocidad de colocación / obtención es mucho más rápida, el JIT también puede realizar optimizaciones mucho mejores en el código final.

Buffers debensolamente ser usado siambos se aplica lo siguiente:

Necesitas procesargrandes cantidades de datos.Esa información es mayoritaria o siempreprocesado en masa.

Tenga en cuenta que un búfer backened tiene una matriz Java que respalda el contenido del búfer. Se recomienda realizar operaciones en este búfer inverso en lugar de poner / obtener bucles.

Los buffers directos deberíansolamente ser usado si te preocupasuso de memoria y nunca acceder a los datos subyacentes. Son un poco más lentos que los buffers no directos, mucho más lentos si se accede a los datos subyacentes, pero utilizan menos memoria. Además, hay una sobrecarga adicional al convertir datos de no bytes (como los arreglos flotantes) en bytes cuando se usa un búfer directo.

Para más detalles ver aquí:

¿Por qué solo los ByteBuffers son útiles cuando se utilizan buffers directos?La sobrecarga interna en NIO y lo que ralentiza los buffersResultados de la muestra

Nota: El porcentaje es solo para facilitar la lectura y no tiene un significado real.

Usando matrices de tamaño 16 con 10,000,000 iteraciones ...
-- 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 matrices de tamaño 1,000 con 100,000 iteraciones ...
-- 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 matrices de tamaño 10,000 con 100,000 iteraciones ...
-- 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%

Respuestas a la pregunta(2)

Su respuesta a la pregunta