Дедупликация строки Java 8 против строки.интерн()
Я читаю о функции в Java 8 update 20 для дедупликации строк (подробнее), но я не уверен, что это в основном делает String.intern() устарело.
Я знаю, что эта функция JVM нуждается в сборщике мусора G1, который может не быть вариантом для многих, но предполагая, что один использует G1GC,есть ли какая-либо разница/преимущество/недостаток автоматической дедупликации, выполняемой JVM vs вручную, чтобы intern строки (один очевидный преимущество заключается в том, что не нужно загрязнять код вызовами intern())?
Это особенно интересно, учитывая, что Oracle может сделать G1GC GC по умолчанию в java 9
3 ответов
С этой функцией, если у вас есть 1000 различных строковых объектов, все с тем же содержимым "abc", JVM может сделать их одинаковыми char[] внутренне. Тем не менее, у вас все еще есть 1000 различных String объекты.
С intern(), у вас будет только один
в качестве ссылок на комментарии см.:http://java-performance.info/string-intern-in-java-6-7-8/. Это очень проницательная ссылка, и я многому научился, однако я не уверен, что ее выводы обязательно "один размер подходит всем". Каждый аспект зависит от потребностей вашего собственного приложения-измерение реалистичных входных данных настоятельно рекомендуется!
основной фактор, вероятно, зависит от того, что вы контролируете:
вы имеете полный контроль над выбором ГК? В приложении GUI, например, все еще есть сильный случай для использования последовательного GC. (гораздо меньший общий объем памяти для процесса-подумайте о 400 МБ против ~1 ГБ для умеренно сложного приложения и гораздо более охотно освобождайте память, например, после переходного всплеска использования). Таким образом, вы можете выбрать это или дать своим пользователям возможность. (Если куча остается маленькой, паузы не должны быть большими).
у вас есть полный контроль над кодом? Опция G1GC отлично подходит для сторонних библиотек (и приложений!), который вы не можете редактировать.
второе соображение (согласно ответу @ ZhongYu )заключается в том, что String.intern может де-дублирования String сами объекты, тогда как G1GC обязательно может только де-дублировать их частные везде, который также работает последовательно, но затем...)
вам, вероятно, не нужна строка де-дублирование везде. Вероятно, есть только определенные области кода, которые:
- действительно влияет на долгосрочное использование кучи,и
- создать высокую долю повторяющихся строк
С помощью String.intern выборочно, другие части кода (которые могут создавать временные или полу-временные строки) не платят цену.
и, наконец, быстрый плагин для утилиты Guava:Интернер, где:
обеспечивает эквивалентное поведение
String.intern()для других неизменяемых типов
вы также можете использовать это для строк. Память, вероятно ,является (и должна быть) вашей главной проблемой производительности, поэтому это, вероятно, не применяется часто: однако, когда вам нужно выжать каждую каплю скорости из некоторой горячей точки, мой опыт заключается в том, что решения HashMap на основе слабых ссылок Java работают немного, но последовательно быстрее, чем реализация c++ JVM String.intern(), даже после настройки параметров JVM. (И бонус: вам не нужно настраивать параметры JVM для масштабирования на другой вход.)
Я хочу ввести еще один фактор принятия решения о целевой аудитории:
- для системного интегратора, имеющего систему, состоящую из множества различных библиотек / фреймворков, с низкой способностью влиять на внутреннее развитие этих библиотек, StringDeDuplication может быть быстрым победителем, если проблема с памятью. Это повлияет на все строки в JVM, но G1 будет использовать только свободное время для этого. Вы даже можете настроить, когда дедупликация рассчитывается с помощью другого параметр(StringDeduplicationAgeThreshold)
- для разработчика, профилирующего свой собственный код, строка.интерн может быть интереснее. Вдумчивый обзор модели домена необходим, чтобы решить, следует ли вызывать стажера, и когда. Как правило, вы можете использовать intern, когда знаете, что строка будет содержать ограниченный набор значений, например, перечисленный набор (т. е. название страны, месяц, день недели...).