Строка против байтового массива, Производительность

(Этот пост касается высокочастотного программирования)

Я недавно видел на форуме (я думаю, что они обсуждали Java), что если вам нужно проанализировать много строковых данных, лучше использовать массив байтов, чем строку с split(). Точный пост был:

Один из приемов работы с любым языком, C++, Java, C#, заключается в том, чтобы избежать создания объектов. Это не стоимость выделения или GC, это стоимость доступа к большим массивам памяти, которые не помещаются в кэш процессора.

Современные процессоры намного быстрее, чем их память. Они останавливаются на много, много циклов для каждого промаха кэша. Большая часть транзисторного бюджета ЦП выделяется для уменьшения этого с большими кешами и большим количеством тиков.

Графические процессоры решают эту проблему по-разному, имея множество готовых к выполнению потоков, чтобы скрыть задержку доступа к памяти и практически не иметь кеша и тратить транзисторы на большее количество ядер.

Так, например, вместо того, чтобы использовать String и split для разбора сообщения, используйте байтовые массивы, которые можно обновить на месте. Вы действительно хотите избежать произвольного доступа к памяти через большие структуры данных, по крайней мере, во внутренних циклах.

Он просто говорит: "Не используйте строки, потому что они являются объектами, а создание объектов обходится дорого"? Или он говорит что-то еще?

Гарантирует ли использование байтового массива данные в кеше как можно дольше? Когда вы используете строку, она слишком велика, чтобы ее можно было хранить в кэше ЦП? Вообще, использование примитивных типов данных - лучший метод для написания более быстрого кода?

2 ответа

Решение

Он говорит, что если вы разбиваете фрагмент текста на отдельные строковые объекты, эти строковые объекты имеют худшую локальность, чем большой массив текста. Каждая строка и массив символов, которые она содержит, будут где-то в памяти; они могут быть распространены повсюду. Вполне вероятно, что кэш-память будет вынуждена входить и выходить, чтобы получить доступ к различным строкам при обработке данных. Напротив, один большой массив имеет наилучшую возможную локализацию, поскольку все данные находятся в одной области памяти, а перегрузка кеша будет сведена к минимуму.

Конечно, есть ограничения: если текст очень, очень большой, и вам нужно только разобрать его часть, то эти несколько маленьких строк могут поместиться в кеше лучше, чем большой кусок текста.

Есть много других причин для использования byte[] или же char* вместо строк для HFT. Струны состоят из 16-битных char в Java и неизменны. byte[] или же ByteBuffer легко перерабатываются, имеют хорошее расположение кеша, могут быть в куче (напрямую), сохраняя копию, избегая кодировщиков символов. Все это предполагает, что вы используете данные ASCII.

char* или ByteBuffers также могут быть сопоставлены с сетевыми адаптерами для сохранения другой копии. (С некоторой возни для ByteBuffers)

В HFT вы редко имеете дело с большими объемами данных одновременно. В идеале вы хотите обрабатывать данные, как только они поступают в Socket. т.е. один пакет за раз. (около 1,5 КБ)

Другие вопросы по тегам