2015-09-29 4 views
13

Я читаю об этой функции в Java 8 update 20 для дедупликации строк (more info), но я не уверен, что это в основном делает String.intern() устаревшим.Java 8 String дедупликация против String.intern()

Я знаю, что для этой функции JVM нужен сборщик мусора G1, который не может быть вариантом для многих, но при условии, что один использует G1GC, есть какая-либо разница/преимущество/недостаток автоматической дедупликации, выполняемой JVM vs вручную с intern ваши строки (одним очевидным является то, что вам не нужно загрязнять ваш код звонками intern())?

Это особенно интересно, учитывая, что Oracle может сделать G1GC GC по умолчанию в Java 9

+3

[Предлагаемое видео] (https://www.youtube.com/watch?v=YgGAUGC9ksk) - но в любом случае, вывод всегда один и тот же: вы. Должен. Не. Забота. – fge

+0

извините, не должен заботиться о чем? о том, какой из них использовать (что означает их эквивалент) или о новой функции (что означает, что это не так полезно)? – Hilikus

+2

Смысл: просто используйте класс 'String' без второй мысли. – fge

ответ

6

С помощью этой функции, если у вас есть 1000 различных объектов String, все с тем же содержанием "abc", JVM может сделать их одни и те же char[] внутренне. Тем не менее, у вас все еще есть 1000 различных объектов String.

С intern() у вас будет только один объект String. Поэтому, если экономия памяти будет вашей проблемой, то лучше будет intern(). Это сэкономит место, а также время GC.

Однако производительность intern() не так уж хороша, в прошлый раз, когда я слышал. Возможно, вам будет лучше, если у вас будет свой собственный кеш строк, даже если вы используете ConcurrentHashMap ... но вам нужно проверить его, чтобы убедиться.

+0

Знаете ли вы о каких-либо других различиях? – Hilikus

+3

На самом деле производительность с String.intern сравнима с ручным пулом строк. Михаил Воронцов сделал некоторые контрольные показатели производительности и показал, что с параметром StringTableSize, установленным достаточно высоким и простым, производительность сравнима с ручным набором строк. [http://java-performance.info/string-intern-in-java-6-7-8/](http://java-performance.info/string-intern-in-java-6-7-8 /) –

2

я хочу представить еще один фактор принятия решения о целевой аудитории:

  • Для системного интегратора, имеющего систему, состоящую многими различными библиотеками/рамок, с низкой способностью влиять на эти библиотеки внутреннее развитие, StringDeDuplication может быть быстрый победитель, если память является проблемой. Это повлияет на все строки в JVM, но G1 будет использовать только свободное время для этого. Вы можете даже настроить, когда DeDuplication вычисляется с использованием другого параметра (StringDeduplicationAgeThreshold)
  • Для разработчиков, профилирующих собственный код, String.intern может быть интереснее. Хотевший обзор модели домена необходим, чтобы решить, следует ли звонить стажером и когда. В качестве эмпирического правила вы можете использовать intern, когда знаете, что String будет содержать ограниченный набор значений, например, определенный набор (например, название страны, месяц, день недели ...).
4

В качестве ссылок на комментарии см.: http://java-performance.info/string-intern-in-java-6-7-8/. Это очень проницательная ссылка, и я многому научился, однако я не уверен, что ее выводы обязательно «один размер подходит всем». Каждый аспект зависит от потребностей вашего собственного приложения - настоятельно рекомендуется проводить измерения реальных входных данных!

Основной фактор, вероятно, зависит от того, что вы находитесь в контроле над:

  • У вас есть полный контроль над выбором GC? Например, в приложении с графическим интерфейсом все еще существует серьезный аргумент в пользу использования Serial GC. (гораздо меньший объем памяти для процесса - думаю, 400 МБ против ~ 1 ГБ для умеренно сложного приложения и гораздо более желательная релиз-память, например, после кратковременного всплеска в использовании). Таким образом, вы можете выбрать это или дать своим пользователям возможность. (Если куча остается маленькой, паузы не должны быть большими).

  • У вас есть полный контроль над кодом?Опция G1GC отлично подходит для сторонних библиотек (и приложений!), Которые вы не можете редактировать.

Второе соображение (в соответствии с @ ответ Zhongyu в) является то, что String.intern может отменить дублирование String самих объектов, в то время как G1GC обязательно могут только де-дублировать свои частные char[] поле.

Третье соображение может быть связано с использованием ЦП, скажем, если влияние на срок службы батареи ноутбука может вызвать озабоченность у ваших пользователей. G1GC запускает дополнительный поток, предназначенный для удаления дубликатов кучи. Например, я играл с этим, чтобы запустить Eclipse, и обнаружил, что он начал начальный период увеличения активности процессора после запуска (думаю, 1 - 2 минуты), но он поселился на небольшой куче «в использовании» и не стал очевидным (просто глаз- свертывание диспетчера задач) Накладные расходы процессора или замедление после этого. Таким образом, я предполагаю, что определенный процент от ядра процессора будет рассмотрен при дедупликации (в течение? После?) Периодов высокой памяти-оттока. (Конечно, могут быть сопоставимые накладные расходы, если вы вызываете String.intern всюду, который также будет работать в серийном, но затем ...)

Вам, вероятно, не требуется разворот строк во всем мире. Есть, вероятно, только некоторые области кода, которые:

  • действительно влияют долгосрочное использование кучи, и
  • создать высокую долю дублированных строк

С помощью String.intern выборочно, другие части кода (который может создавать временные или полу-временные строки) не оплачивают цену.

И, наконец, быстрый разъем для утилиты Гуавы: Interner, что:

Обеспечивает эквивалентное поведение String.intern() для других неизменных типов

Вы также можете использовать это для струнных. Возможно, память (и должна быть) связана с вашей максимальной производительностью, поэтому это, вероятно, часто не применяется: однако, когда вам нужно сжимать каждую капли скорости из какой-либо области с горячей точкой, мой опыт в том, что слабая ссылка на Java Решения HashMap работают немного, но последовательно быстрее, чем реализация JVM C++ String.intern(), даже после настройки параметров jvm. (И бонус: вам не нужно настраивать параметры JVM для масштабирования на разные входные данные.)

Смежные вопросы