String.intern() действительно увеличивает производительность?

Я провел небольшое расследование, чтобы выяснить, как String.intern() Метод реализован в Java.

Я посмотрел на C++ реализацию Intern pool из Open JDK 6 и там увидел простой HashSet, Для меня это означало, что когда кто-то пытается интернировать String следующие шаги должны быть сделаны:

  1. найти хеш-код, связанный с данным String
  2. найти подходящее ведро
  3. сравнивая данную строку со всеми другими строками в корзине. Перед этим шагом может быть 0 строк, одна строка или много строк в сегменте. Поэтому, если указанная строка была ранее помещена в корзину, мы получим хотя бы одно сравнение (это лучший случай. Конечно, могло быть много столкновений, и теперь в корзину входит много других строк).
  4. Если строка была найдена в корзине, она должна быть возвращена intern() метод
  5. Если Строка не была найдена в ведре, тогда это должно быть помещено в ведро и возвращено intern() метод

Так много людей говорят, что str1.intern() == str2.intern() будет быстрее, чем str1.equals(str2),

Но я не вижу причины, по которой это должно быть быстрее.

Как я вижу в случае str1.equals(str2) у нас всегда есть две строки, сравнивающие char с char в String.equals() метод.

В случае str1.intern() == str2.intern()Сколько сравнений мы должны были бы получить или поместить строку в / из пула (верно, это может быть много сравнений, и они также являются простыми сравнениями по типу char)?

Так что в случае str1.intern() == str2.intern() даже если мы используем == для сравнения строк у нас также будет много дополнительных действий, таких как сравнение, описанное ранее.

Когда я понял это, я решил провести некоторое тестирование.

Первые результаты показали мне, что str1.intern() == str2.intern() был быстрее чем str1.equals(str2),

Такое поведение было вызвано тем, что String.intern() метод является родным, поэтому его не следует интерпретировать каждый раз и String.equals() это метод Java

Итак, я решил использовать -Xcomp возможность заставить JVM компилировать весь код при запуске.

После этого показал лучшую скорость, чем стажер.

Я проверил это на Java 6 и 7.

Итак, мой вопрос: вы когда-нибудь видели ситуацию, когда интернирование увеличивало скорость сравнения строк? Я да как это может быть?

Или, может быть intern() может помочь только сэкономить больше свободной памяти?

2 ответа

String.intern() предназначен для уменьшения использования памяти.

Используйте интернированные строки (если вообще когда-либо), когда у вас много-много копий одной и той же строки в памяти. интернируя строки, все эти копии будут использовать одну и ту же ссылку.

Я видел, что интернирование строк полезно, когда у меня есть миллионы копий одной и той же строки.

Как и в случае любого вида оптимизации, делайте это только после того, как возникнет проблема с производительностью или памятью, и вы профилировали ее, чтобы обнаружить, что это узкое место.

См. Этот пост в блоге для более подробной информации об интернировании строк.

На ваш вопрос о том, почему str1.intern() == str2.intern() может быть быстрее:

Это String.equals() реализация - как вы можете видеть, это может быть очень неэффективно в зависимости от сравниваемых строк.

public boolean equals(Object anObject) {
    if (this == anObject) {
        return true;
    }
    if (anObject instanceof String) {
        String anotherString = (String) anObject;
        int n = value.length;
        if (n == anotherString.value.length) {
            char v1[] = value;
            char v2[] = anotherString.value;
            int i = 0;
            while (n-- != 0) {
                if (v1[i] != v2[i])
                        return false;
                i++;
            }
            return true;
        }
    }
    return false;
}

Ваши шаги могут быть намного быстрее:
1) hashCode () вычисляется один раз для любой строки из-за ее неизменности и довольно быстро
2) найти ведро O (1)
3) Сравнение вашей строки с другими в одном ведре - может быть, несколько, но все же должно быть быстрее, чем equals()
4) и 5) быстро

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

Другие вопросы по тегам