Pull to refresh

Comments 11

За задачи и разбор +1, но делать выводы о производительности по байткоду не совсем корректно, как я показывал в презентации. Замени, например, timestamp с long на int и сравни заново… Довод про конструктор StringBuilder развалился на глазах, правда? И выводы будут уже совсем другие.

В этой же презентации про конкатенацию, кстати, тоже есть. Нельзя бенчмаркать StringBuilder и не упомянуть фичу Хотспота под названием OptimizeStringConcat.
За задачи и разбор +1, но делать выводы о производительности по байткоду не совсем корректно, как я показывал в презентации.

Спасибо!
За исключением тех случаев, когда javac генерирует идентичный байткод. :) В остальном согласен, и чем дальше (тот же JEP-280), тем поведение JIT-компилятора становится менее предсказуемым.

В этой же презентации про конкатенацию, кстати, тоже есть. Нельзя бенчмаркать StringBuilder и не упомянуть фичу Хотспота под названием OptimizeStringConcat.

О, точно, я уже под утро заканчивал статью и про OptimizeStringConcat совсем забыл, а это важная штука.

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

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

Согласен, в этом месте влияние JIT не настолько существенное — выше Андрей apangin намекнул на различия в определении длины строки под long в StringBuilder и StringConcatFactory. apangin, я же правильно понял, что речь об этом?

Да, и ещё то, что с int типом будет уже не важно, создаётся ли StringBuilder() с размером по умолчанию или StringBuilder(metrics) с заранее предопределённым размером. В обоих случаях паттерн new StringBuilder(*).append()...append().toString() скомпилируется как интринсик без вызова Java кода, и производительность Concatenation vs. StringBuilder будет одинаковая, несмотря на различия в байткоде.


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

Ага, я чуть позже про OptimizeStringConcat дописал.

Если же в цепочке попадётся append(long), то оптимизация не отработает — ну, не реализовали почему-то в JDK 8), то есть, будет честный вызов Java кода.
Судя по изменениям в stringopts.cpp в JDK 10/JDK 9 относительно JDK 8, то в новых версиях это по-прежнему не оптимизируется.
Ну так потому что уже особо не надо: JEP-280 срабатывает в подавляющем большинстве случаев (кроме модуля java.base и вручную написанных StringBuilder'ов). По сути дела и существующую оптимизацию если удалить, сильно хуже не станет.
Как сказать… не пересобирать же из исходников все 100500 подключаемых библиотек, скомпилированных под Java 6-7-8.
Я думаю, какой-нибудь jlink проще научить обновлять байткод в таких ситуациях. Все же пользуются jlink начиная с Java 9 ;-)
Sign up to leave a comment.