Developer Tales or everything about everything

9Июн/123

Конкатенация строк в Java

Время выполнения методов конкатенации

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

Конкатенация в Java

Любая строка, будь то переменная или константа, в Java является объектом типа String. Этот факт упрощает работу со строками, но, в то же время, требует наличия определенных знаний для правильной работы с ними.

Рассмотрим ситуацию: необходимо просканировать много текстовых файлов больших или средних размеров и работать с полным текстом файла, либо с большими кусками с необходимостью осуществления конкатенации строк. Цель сканирования в контексте данной темы не важна, важен принцип чтения строк и их конкатенации.

Итак, решение в лоб:

Хм.. Ну, вроде бы, все ок? Ладно, ну а если для сканирования предлагается порядка 2-3 тысяч файлов с размером от 500 Кб до 2-3 Мб?

Проблема конкатенации с помощью оператора '+' в том, что Java каждый раз создает новую копию объекта StringBuilder, копирует в StringBuilder поочередно исходную и сочленяемую строку, затем возвращает результарующую строку. Это можно увидеть, посмотрев в байт-код:

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

Варинтов решения в данном случае 3:

  • Использовать метод String.concat();
  • Использовать объект StringBuffer;
  • Использовать объект StringBuilder.

Поговорим о каждом способе отдельно.

Конкатенация с помощью String.concat()

Метод concat направлен на оптимизированную конкатенацию строк. Однако, он все равно не является лучшим выбором для оптимизации, проигрывает в скорости выполнения StringBuffer & StringBuilder, да к тому же, читабельность кода при его использовании сильно ухудшается (это справедливо и для StringBuffer & StringBuilder). Решение с использованием concat:

StringBuffer

StringBuffer осуществляет конкатенацию строк очень оптимально, вследствие чего повышается скорость выполнения приложения. Однако, он проигрывает объекту StringBuilder. А проигрывает потому что предоставляет ряд дополнительных свойств, среди которых безопасное выполнение в потоках, то есть StringBuffer является Thread-Safe объектом. Из-за этого немного падает производительность данного объекта, но повышается удобство его использования при асинхронном доступе к данным из разных потоков.

StringBuilder

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

Конечно, все эти доводы не заставляют использовать String.concat, StringBuffer или StringBuilder каждый раз, когда нужно сложить несколько строк - это очень затрудняет как чтение кода, так и сам процесс разработки. Для небольшого количества конкатенаций (порядка 4-5 операций), которые не содержатся в циклах, можно спокойно использовать обычный оператор +=. Если конкатенация находится в цикле, то лучше всего использовать StringBuilder. Если предполагается возможность одновременного доступа к одним и тем же данным из нескольких потоков приложения во время конкатенации, то следует использовать StringBuffer.

Опции JVM

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

-XX:+DoEscapeAnalysis

При использовани ключа DoEscapeAnalysis, JVM анализирует области видимости используемых переменных как в разрезе методов и блоков кода, так и в разрезе потоков. В результате такой оптимизации StringBuffer может быть неявно преобразован в StringBuilder (в случае, если объект гарантированно находится в области видимости только одного потока).

-XX:+OptimizeStringConcat

Ключ OptimizeStringConcat говорит сам за себя: при его использовании JVM попытается самостоятельно проанализировать участки кода, где используется конкатенация строк, и максимаьлно оптимизировать этот процесс так, чтобы выделить память только один раз.

Использование ключей, конечно же, не гарантирует наилучшую оптимизацию кода. Однако, автоматическая оптимизация может помочь избежать Performance Miss'ов, допущенных по незнанию или по невнимательности.

В заключении представлю график времени выполнения чтения одних и тех же файлов для всех четырех способов конкатенации:

Время выполнения методов конкатенации

Как видно по графику, оператор += просто колоссально проигрывает в скорости выполнения остальным способам. Конкретные цифры такие:

  • Оператор += - 92.243 с;
  • String.concat() - 1.254 с;
  • StringBuffer - 1.208 с;
  • StringBuilder - 1.121 с.

Ссылки

Просмотров: 8436
Комментарии (3) Пинги (0)
  1. Всё круто! Спасибо!

  2. wholeText.concat(line);
    Тут наверно всё же
    wholeText = wholeText.concat(line);
    Т.к. concat не меняет исходный объект


Отменить ответ


девять × 1 =

http://microfork.com/wp-content/plugins/wp-monalisa/icons/wpml_bye.gif 
http://microfork.com/wp-content/plugins/wp-monalisa/icons/wpml_good.gif 
http://microfork.com/wp-content/plugins/wp-monalisa/icons/wpml_negative.gif 
http://microfork.com/wp-content/plugins/wp-monalisa/icons/wpml_scratch.gif 
http://microfork.com/wp-content/plugins/wp-monalisa/icons/wpml_wacko.gif 
http://microfork.com/wp-content/plugins/wp-monalisa/icons/wpml_yahoo.gif 
http://microfork.com/wp-content/plugins/wp-monalisa/icons/wpml_cool.gif 
http://microfork.com/wp-content/plugins/wp-monalisa/icons/wpml_heart.gif 
http://microfork.com/wp-content/plugins/wp-monalisa/icons/wpml_rose.gif 
http://microfork.com/wp-content/plugins/wp-monalisa/icons/wpml_smile.gif 
http://microfork.com/wp-content/plugins/wp-monalisa/icons/wpml_whistle3.gif 
http://microfork.com/wp-content/plugins/wp-monalisa/icons/wpml_yes.gif 
http://microfork.com/wp-content/plugins/wp-monalisa/icons/wpml_cry.gif 
http://microfork.com/wp-content/plugins/wp-monalisa/icons/wpml_mail.gif 
http://microfork.com/wp-content/plugins/wp-monalisa/icons/wpml_sad.gif 
http://microfork.com/wp-content/plugins/wp-monalisa/icons/wpml_unsure.gif 
http://microfork.com/wp-content/plugins/wp-monalisa/icons/wpml_wink.gif 
 

Trackbacks are disabled.