Ответ 1
Я немного поработал с бенчмаркингом. Для части стоимости поиска я решил сравнить String.intern() с ConcurrentHashMap.putIfAbsent(s, s). В принципе, эти два метода выполняют одни и те же функции, кроме String.intern() - это собственный метод, который хранит и считывает из SymbolTable, который управляется непосредственно в JVM, а ConcurrentHashMap.putIfAbsent() - обычный метод экземпляра.
Вы можете найти контрольный код github gist (из-за отсутствия лучшего места для его размещения). Вы также можете найти параметры, которые я использовал при запуске JVM (чтобы убедиться, что эталон не перекошен) в комментариях в верхней части исходного файла.
В любом случае, вот результаты:
Стоимость поиска (однопоточная)
Легенда
- count: количество отдельных строк, которые мы пытаемся объединить.
- начальный стажер: время в мс потребовалось, чтобы вставить все строки в пул строк
- найдите ту же строку: время в секундах, которое потребовалось для поиска каждой строки из пула, используя тот же экземпляр, который ранее был введен в пул
- lookup equal string: время в секундах, которое потребовалось для поиска каждой из строк снова из пула, но с использованием другого экземпляра
String.intern()
count initial intern lookup same string lookup equal string
1'000'000 40206 34698 35000
400'000 5198 4481 4477
200'000 955 828 803
100'000 234 215 220
80'000 110 94 99
40'000 52 30 32
20'000 20 10 13
10'000 7 5 7
ConcurrentHashMap.putIfAbsent()
count initial intern lookup same string lookup equal string
1'000'000 411 246 309
800'000 352 194 229
400'000 162 95 114
200'000 78 50 55
100'000 41 28 28
80'000 31 23 22
40'000 20 14 16
20'000 12 6 7
10'000 9 5 3
Вывод для стоимости поиска: String.intern() на удивление дороже вызова. Он очень сильно масштабируется, что-то вроде O (n), где n - количество строк в пуле. Когда количество строк в пуле растет, количество времени для поиска одной строки из пула растет намного больше (0,7 микросекунды на поиск с 10 000 строк, 40 микросекунд на поиск с 1'000'000 строк).
ConcurrentHashMap масштабируется, как ожидалось, количество строк в пуле не влияет на скорость поиска.
Основываясь на этом эксперименте, я настоятельно рекомендую избегать использования String.intern(), если вы собираетесь ставить более нескольких строк.