Добрый день. Известно, что хэшкод для строк кэшируется в поле hash в момент первого вызова методы hashCode(), и для последующих вызовов не рассчитывается. Далее, есть такой код:
public static void main(String[] args) {
int hashInt = 0;
String one = "qwersdfdsfsfdstyuiop";
long start = System.nanoTime();
hashInt = one.hashCode();
System.out.println(System.nanoTime() - start + " : " + hashInt);
String two = "poiuytradadasda";
start = System.nanoTime();
hashInt = two.hashCode();
System.out.println(System.nanoTime() - start + " : " + hashInt);
}
результат:
125701 : -1509822895
766 : 1617334817
Откуда такая разница во времени? Спасибо за ответы.
JVM загружает и компилирует в нативный код используемые классы и методы по мере необходимости. При первом обращении к System.out
, String.hashCode
загружаются по цепочке используемые классы, методы компилируются в нативный код.
Если при запуске Java указать флаг -XX:+PrintCompilation
, то можно увидеть какие методы компилируются на лету:
70 1 3 java.lang.String::hashCode (55 bytes)
71 3 3 java.lang.String::equals (81 bytes)
72 2 3 java.lang.Object::<init> (1 bytes)
72 7 n 0 java.lang.System::arraycopy (native) (static)
73 6 3 java.lang.String::indexOf (70 bytes)
73 4 3 java.lang.String::<init> (82 bytes)
74 5 3 java.util.Arrays::copyOfRange (63 bytes)
74 11 3 java.lang.String::charAt (29 bytes)
75 9 3 java.lang.CharacterData::of (120 bytes)
75 10 3 java.lang.CharacterDataLatin1::getProperties (11 bytes)
76 12 3 java.lang.String::length (6 bytes)
76 13 3 java.lang.Character::toLowerCase (9 bytes)
76 8 3 java.lang.Math::min (11 bytes)
77 14 3 java.lang.CharacterDataLatin1::toLowerCase (39 bytes)
82 15 3 java.lang.AbstractStringBuilder::ensureCapacityInternal (27 bytes)
84 16 3 java.lang.AbstractStringBuilder::append (29 bytes)
85 17 3 java.lang.StringBuilder::append (8 bytes)
85 18 3 java.io.WinNTFileSystem::isSlash (18 bytes)
86 20 4 java.lang.String::charAt (29 bytes)
86 19 s 3 java.lang.StringBuffer::append (13 bytes)
87 11 3 java.lang.String::charAt (29 bytes) made not entrant
90 21 3 java.lang.StringBuilder::append (8 bytes)
Мораль здесь такова, что бенчмарки писать сложно ибо существует масса влияющих факторов, например:
Чтобы снизить влияние по крайней мере первого фактора, нужно до измерений запустить цикл «прогрева» в котором загрузятся и скомпилируются все используемые методы.
Например, если добавить цикл прогрева и отделить вывод, то можно получить уже более стабильные результаты:
class Test {
private final String value;
private int hash;
private long time;
public Test(String value) {
this.value = value;
}
//измеряем hashcode
public void measure() {
long start = System.nanoTime();
hash = value.hashCode();
time = System.nanoTime()-start;
}
//печатаем
private void print() {
System.out.println(time + " : " + hash);
}
public static void main(String[] args) {
warmup();
runTests();
}
//прогрев
private static void warmup() {
for(int i=0; i<10; i++) {
Test test = new Test(i+"");
test.measure();
}
}
//наши тесты
private static void runTests() {
Test[] tests = new Test[] {
new Test("qwersdfdsfsfdstyuiop"),
new Test("poiuytradadasda")
};
for(Test test : tests) {
test.measure();
}
for(Test test : tests) {
test.print();
}
}
}
В этом коде разница уже будет не такой ощутимой, хотя еще осталась масса проблем: System.nanoTime
неточен на одиночных вычислениях, не учитывается сборщик мусора и пул строк.
Подбробнее о проведении микроизмерений можно почитать в обсуждении в английском Stackoverflow: How do I write a correct micro-benchmark in Java?. Там же есть ссылки на популярные инструменты для данных целей.
Кофе для программистов: как напиток влияет на продуктивность кодеров?
Рекламные вывески: как привлечь внимание и увеличить продажи
Стратегії та тренди в SMM - Технології, що формують майбутнє сьогодні
Выделенный сервер, что это, для чего нужен и какие характеристики важны?
Современные решения для бизнеса: как облачные и виртуальные технологии меняют рынок
Что нужно дописать в код, чтобы текст обновлялся на кнопке раз в секунду, или ткните где искать инфу, заранее благодарю
Ломаю голову второй деньНеобходимо программно менять цвет у элементов ExpListView (Не родителей)
Добрый деньСоздал веб-проект с применением технологий (Tomcat, JDBC, JSP, Servlets, Maven etc)