Окей — какие перформанс проблемы есть у intern с точки зрения его использования самой jvm? никаких — раньше был один размер таблицы — с увеличением внутренних нужд эту внутреннюю кухню чуть расширили.
А т.к. она не предназначена для работы вне jvm — то и проблемы индейцев инженеров jvm тоже не волнуют.
Данная тема, intern(), является настолько избитой, что кажется странно о ней уже говорить снова и снова.
Как минимум странно говорить о ней, когда это уже 2ая часть подобной статьи, и в 1ой части не могли не сослаться (пусть и в комментариях) на доклад Алексея Шипилёва
и, конечно же, Катехизис: java.lang.Stringhttps://youtu.be/SZFe3m1DV1A?t=1913 — здесь я специально привёл момент, где подробно и в деталях рассказывают почему intern() это зло.
+ чуть ниже я привёл ссылку на проблему с которой можно столкнуться при использовании jackson (а если у вас есть REST API или вы как-то работаете со json — то скорее всего вы столкнётесь именно с ним): https://github.com/FasterXML/jackson-core/issues/332
Почитайте и посмотрите какие проблемы (на пустом месте) и лишние доп. расходы всплывают при этом (и не у меня одного — этот prod профиль фееричен), но автору jackson эти доводы не зашли (сразу).
Можно ещё добавить про то, что intern hash table, которая реализована на уровне VM не расширяется. Ещё в бытность java 6 проводил эксперимент с intern и пересборкой java из сорсов, но это меркнет на фоне докладов и статей Шипилёва.
Надеюсь, что, теперь у вас есть более развёрнутый ответ на данную тематику и вы будете нести свет другим.
Надеюсь не сильно перевру если опишу историю кратко — JEP делал не безызвестный Алексей Шипилёв — и что согласно профилям приложений который активно работали с не latin-1 строками (имена не назывались, но представьте себе региональные социальные сети) — и даже в их случае количество latin-1 строк было достаточно высокое (не 50%, но и не 10%). Среди прочего это и внутри vm вещи — имена классов и т.п.
Почему не бит — вопрос в том как его хранить с кем его есть — опять же — бенчмарки показали, что так (с флагом) будет лучше.
Do not, under any circumstances, run Lucene with the G1 garbage collector. Lucene's test suite fails with the G1 garbage collector on a regular basis, including bugs that cause index corruption.
Учитывая то, что баг ( bugs.openjdk.java.net/browse/JDK-8038348 ) на который ругаются таки закрыли — сейчас идёт long run test на G1 и если новых проблем не будет — то партия даст добро.
С GCG1 на ранних сборках 8ки (и кажется даже 10ки) наблюдали забавные глюки — собственно поэтому официально этот сборщик не поддерживается, но в планах его включить т.к. CMS уже помечен как deprecated в 10ке, и Oracle/OpenJDK настоятельно рекомендуют именно G1.
Понятно, что может — никто из этого никого секрета не делает — open source же. Я про то, что из коробки нельзя вытащить отдельные файлы snapshot'а — в силу специфики Lucene там могут оказаться куски предыдущего snapshot'а, которые мешать не будут, но будут занимать место.
Забавно, но буквально сегодня клиент спрашивал — как вытащить последний snapshot из кучи. Может стоит оформить ticket?
Согласен, но в целом ES уделяет большое внимание backward-compatibility, и braking changes по возможности делать как можно меньше — если только уже совсем никак. Но и старый воз костылей не хочется ни тащить, ни поддерживать.
а если быть ещё точнее — начиная с 8ки (или 7ки?) — то если уровень коллизий больше некоторого числа (8-10) и ключ Comparable — то там будет вообще красно-чёрное дерево!
Я бы поспорил про ленивую инициализацию ArrayList / HashMap — начиная с какого-то билда 8ки — с конструктором по-умолчанию они внутри пустые — т.е расход только идёт на объект-обёртку (16байт?) но нет головных болей с null-reference и прочим усложнением lazy initialization.
Если уж так хочется экономить на спичках — то стоит ещё вспомнить про autoboxing — и что это ещё тот overhead — как по памяти, так и по производительности (derefence тоже не бесплатный) — и есть для этого специализированные коллекции — trove, koloboke, eclipse collections etc.
И самое главное, что кажется тут возможно подразумевается, но упущено — можно было сделать ArrayList, который бы всегда ужимался — но тогда будет страдать производительность, можно использовать TreeMap вместо HashMap (что фактически сделано в c++ с std::map) — это разумный trade-off — вы уж выбирайте — шашечки или ехать.
Согласен, что если так сильно запаривает память — то выделяй для ArrayList размер (если он известен), после можно делать trimToSize, или вызывать copy-ctor — это и для ArrayList/HashMap/CHM/HashSet и т.п справедливо.
Спасибо за ссылку. Берём jmh benchmark из JVM Anatomy Park #10: String.intern() и java 11 (build 11+28) запускаем — смотрим
для случая, когда нужна дедупликация
intern()
(а ведь именно на этот use-case по сути указывал автор статьи) — плохой выбор.А т.к. она не предназначена для работы вне jvm — то и проблемы индейцев инженеров jvm тоже не волнуют.
Это торчащая наружу ручка от самой JVM и Вам туда не надо — если сильно надо — то можно подкрутить размер hash table. Точка.
@Deprecated
так на него и не навесили.Данная тема,
intern()
, является настолько избитой, что кажется странно о ней уже говорить снова и снова.Как минимум странно говорить о ней, когда это уже 2ая часть подобной статьи, и в 1ой части не могли не сослаться (пусть и в комментариях) на доклад Алексея Шипилёва
The Lord of the Strings https://www.youtube.com/watch?v=HWkVJkoo1_Q
и, конечно же, Катехизис: java.lang.String https://youtu.be/SZFe3m1DV1A?t=1913 — здесь я специально привёл момент, где подробно и в деталях рассказывают почему
intern()
это зло.+ чуть ниже я привёл ссылку на проблему с которой можно столкнуться при использовании jackson (а если у вас есть REST API или вы как-то работаете со json — то скорее всего вы столкнётесь именно с ним): https://github.com/FasterXML/jackson-core/issues/332
Почитайте и посмотрите какие проблемы (на пустом месте) и лишние доп. расходы всплывают при этом (и не у меня одного — этот prod профиль фееричен), но автору jackson эти доводы не зашли (сразу).
+ нельзя не упоминуть JVM Anatomy Park (всё того же А. Шипилёва) и в частности, что касается
intern()
: JVM Anatomy Park #10: String.intern()Можно ещё добавить про то, что intern hash table, которая реализована на уровне VM не расширяется. Ещё в бытность java 6 проводил эксперимент с intern и пересборкой java из сорсов, но это меркнет на фоне докладов и статей Шипилёва.
Надеюсь, что, теперь у вас есть более развёрнутый ответ на данную тематику и вы будете нести свет другим.
https://github.com/FasterXML/jackson-core/issues/332
Не делайте
String#intern()
. Н И К О Г Д А.Почему не бит — вопрос в том как его хранить с кем его есть — опять же — бенчмарки показали, что так (с флагом) будет лучше.
LUCENE-6098: Indexwriter changecount assertion fail with g1gc и целый список от Lucene:
Учитывая то, что баг ( bugs.openjdk.java.net/browse/JDK-8038348 ) на который ругаются таки закрыли — сейчас идёт long run test на G1 и если новых проблем не будет — то партия даст добро.
Забавно, но буквально сегодня клиент спрашивал — как вытащить последний snapshot из кучи. Может стоит оформить ticket?
Есть ломающие изменения (breaking changes), которые опять-таки описаны — но в целом 6ка должна читать индексы 5ки.
Если уж так хочется экономить на спичках — то стоит ещё вспомнить про autoboxing — и что это ещё тот overhead — как по памяти, так и по производительности (derefence тоже не бесплатный) — и есть для этого специализированные коллекции — trove, koloboke, eclipse collections etc.
И самое главное, что кажется тут возможно подразумевается, но упущено — можно было сделать ArrayList, который бы всегда ужимался — но тогда будет страдать производительность, можно использовать TreeMap вместо HashMap (что фактически сделано в c++ с std::map) — это разумный trade-off — вы уж выбирайте — шашечки или ехать.
Согласен, что если так сильно запаривает память — то выделяй для ArrayList размер (если он известен), после можно делать trimToSize, или вызывать copy-ctor — это и для ArrayList/HashMap/CHM/HashSet и т.п справедливо.