Когда использовать массив, буфер или прямой буфер

Вопрос

При написании класса Matrix для использования с библиотеками OpenGL я столкнулся с вопросом, использовать ли массивы Java или стратегию Buffer для хранения данных (JOGL предлагает копирование с прямым буфером для операций Matrix). Чтобы проанализировать это, я написал небольшую программу тестирования производительности, которая сравнивает относительные скорости циклических и массовых операций в массивах против буферов против прямых буферов.

Я хотел бы поделиться своими результатами с вами здесь (поскольку я нахожу их довольно интересными). Пожалуйста, не стесняйтесь комментировать и / или указывать на любые ошибки.
Код можно посмотреть наpastebin.com/is7UaiMV.

Примечания

Loop-read массив реализован какA [i] = B [i] иначе оптимизатор JIT полностью удалит этот код. фактическийvar = A [i] кажется, в значительной степени то же самое.

В приведенном примере результатов для размера массива 10000 весьма вероятно, что оптимизатор JIT заменил доступ к зацикленному массиву реализацией, подобной System.arraycopy.

Там нет массового получения буфера-> буфер, как реализует JavaA.get (В) какB.put (А)следовательно, результаты будут такими же, как и объемные результаты.

Заключение

Практически во всех ситуациях настоятельно рекомендуется использовать внутренние массивы Java. Мало того, что скорость ввода / вывода значительно выше, JIT также может выполнять намного лучшую оптимизацию конечного кода.

Буферы должнытолько использоваться, еслиобе применяется следующее:

Вам нужно обработатьбольшое количество данных.Эти данные в основном или всегдаОсновная часть обработанных.

Обратите внимание, что backened-buffer имеет Java Array, поддерживающий содержимое буфера. Рекомендуется выполнять операции с этим обратным буфером вместо цикла put / get.

Прямые буферы должнытолько использовать, если вы беспокоитесь оиспользование памяти и никогда не получить доступ к базовым данным. Они немного медленнее, чем непрямые буферы, намного медленнее при обращении к базовым данным, но используют меньше памяти. Кроме того, существуют дополнительные издержки при преобразовании небайтовых данных (таких как массивы с плавающей запятой) в байты при использовании прямого буфера.

Для более подробной информации смотрите здесь:

Почему только ByteBuffers полезны при использовании прямых буферовВнутренние издержки на NIO и что замедляет буферыПример результатов

Примечание: процент только для удобства чтения и не имеет никакого реального значения.

Использование массивов размером 16 с 10 000 000 итераций ...
-- 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%
Использование массивов размером 1000 с 100 000 итераций ...
-- 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%
Использование массивов размером 10 000 с 100 000 итераций ...
-- 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%

Ответы на вопрос(2)

Ваш ответ на вопрос