- PVSM.RU - https://www.pvsm.ru -

Performance это праздник

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

https://xkcd.com/1781/

JPoint 2017 открывался с мега пленарного доклада Алексея Шипилёва, который он анонсировал ёщё в октябре 2016 на Joker — тогда я смотрел его online и проникся Кривой им Ш [1]:

Кривая им. Ш

И если с зелёной и красной зоной как-то более-менее ясно-понятно, то вот с границей зеленой-жёлтой не всё так очевидно — что это? можно пример ?

System.arraycopy

Начнём с эпичного срача вопроса — что быстрее — ручной джедайский меч

for (int i = 0; i < src.length; i++)
   target[i] = src[i];

или расово верный System.arraycopy.

На данный момент векторизация и intrinsic [2] делают оба варианта равнозначными — вопрос вкусовых предпочтений.

collection.toArray()

Есть коллекция, например, строк, и хотим получить массив.

Лучшее (враг хорошего) решение:

String[] array = collection.toArray(new String[collection.size]);

Забудь!

Arrays of Wisdom of the Ancients [3] учит, что новое это хорошо забытое старое

String[] array = collection.toArray(new String[0]);

new ArrayList

Раньше (когда деревья были высокими) при создании экземпляра ArrayList / HashMap / etc внутри создавался массив с начальным размером ( 10 для ArrayList, 0x10 для HashMap ).

Другое дело, когда вы заранее знали, какое количество элементов вы собираетесь положить в коллекцию — опытные джедаи создают сразу что-то типа

List<String> strings = new ArrayList<>( values.length );

сразу запихиваете свои values и счастье — никаких паразитных аллокаций от 10 элементов до вашей цели.

Но что, если самих значений ещё нет — с null возится не хочется, но знаем, что будет не больше, например, трёх?

List<String> strings = new ArrayList<>( 3 );

И погнали — профит в 7 сэкономленных ячеек на каждый такой список ( ~7 * 16 байт / список ), который когда-то да будет заполнен.

Забудь!

Optimize empty HashMap and ArrayList [4] коммит в openjdk — теперь все ArrayList / HashMap, созданные от конструктора по-умолчанию держат пустую static заглушку — и первое же добавление создаст массив на 10 элементов (для ArrayList, 16 для HashMap), тогда как new ArrayList( int ) создаёт массив энергично и сразу.

String.split(regex)

Что знают джедаи про регулярные выражения?
https://xkcd.com/208/

Компилировать regexp каждый раз — дорого, опытные падаваны делают вместо stringValue.split(regexp) что-то типа

private static final Pattern PATTERN = Pattern.compile(regex);

....
String[] strings = PATTERN.split(stringValue);

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

Забудь!

Забудь!

Lightweight implementation of String.split for simple use case [5]

Если у вас односимвольный разделитель — именно разделитель типа ( пробел ) или , ( запятая ), а не спец. символ регулярного выражения типа . ( точка ) — то никакое регулярное выражение даже и близко не создаётся.

Код, который пахнет

Я не буду даже говорить про код, который явно пахнет типа

return new StringBuilder().append("value:").append(value).toString();

пользы от него никакой — зато читаемость никакая.

XX-флаги

Можно очень крапотливо подбирать размеры кучи и прочие XX-флаги — но со временем, когда в код проекта влито ещё 1000 и 1 одна бизнес фича все эти флаги могут более, чем запросто не приносить желаемого результата быстроты. Считайте они протухли.

Выводы

Если ваш проект жив и процветает, а вас раз в сто-двести лет просят устроить перформанс (хотя танцы голым на пьяных столах тоже перформанс, но я немного о другом ) — то появляются всякого рода оптимизации, и не исключено, что из той самой жёлтой зоны, которые по истечению срока годности начинают не просто пахнуть, но и делать обратную задачу от изначальной — тормозить приложение.

Performance это праздник - 5

Надежды нет, что анализаторы типа PMD, или ваша любимая IDE имеют актуальные рекомендации именно для той версии java, на которой вы запускаеть в PROD ==>

Проводите ревизию магических приёмов знаний.

Автор: Владимир Долженко

Источник [6]


Сайт-источник PVSM.RU: https://www.pvsm.ru

Путь до страницы источника: https://www.pvsm.ru/java/252421

Ссылки в тексте:

[1] Кривой им Ш: http://www.habrahabr.net/thread/3729

[2] intrinsic: http://hg.openjdk.java.net/jdk8/jdk8/hotspot/file/87ee5ee27509/src/share/vm/classfile/vmSymbols.hpp#l581

[3] Arrays of Wisdom of the Ancients: https://shipilev.net/blog/2016/arrays-wisdom-ancients/

[4] Optimize empty HashMap and ArrayList: http://hg.openjdk.java.net/jdk8/jdk8/jdk/rev/0cccdb9a9a4c

[5] Lightweight implementation of String.split for simple use case: http://hg.openjdk.java.net/jdk8/jdk8/jdk/rev/1ff977b938e5

[6] Источник: https://habrahabr.ru/post/326242/