Тесты производительности
В мире придумано уже очень много алгоритмов. Все они в том или ином виде реализованы в языках программирования и хранятся в библиотеках. Все кто использует стандартную библиотеку получают более менее стандартный результат. Многие люди стараются превзойти этот результат и написать более быстрые алгоритмы или более эффективные. Для того, чтобы сравнить два алгоритма, надо проводить тестирование производительности. Это довольно сложная тема, о которой много пишет Шипилев. Он же является ответственным за инструмент для проведения бенчмарков на java JMH.
Документации по JMH довольно мало. Я нашел следующие источники информации:
- Доклады Шипилева
- Stackoverflow
- Примеры из исходников
Это позволило мне написать свой первый простой и возможно не очень показательный бенчмарк:
package ru.yamakarov;
import java.util.HashMap;
import java.util.Map;
import java.util.TreeMap;
import org.openjdk.jmh.annotations.Benchmark;
import org.openjdk.jmh.annotations.Scope;
import org.openjdk.jmh.annotations.State;
import org.openjdk.jmh.runner.Runner;
import org.openjdk.jmh.runner.RunnerException;
import org.openjdk.jmh.runner.options.Options;
import org.openjdk.jmh.runner.options.OptionsBuilder;
public class JavaMapBenchmark {
private static final int ITEM_COUNT = 100_000;
@State(Scope.Benchmark)
public static class BenchMarkState {
private Map<String, Object> treeMap = new TreeMap<>();
private Map<String, Object> hashMap = new HashMap<>();
private int counter;
public BenchMarkState() {
for(int i = 0; i < ITEM_COUNT; i++) {
treeMap.put(String.valueOf(i), new Object());
hashMap.put(String.valueOf(i), new Object());
}
}
private String getKey() {
if (counter == ITEM_COUNT) {
counter = 0;
}
return String.valueOf(counter++);
}
}
@Benchmark
public void testTreeMap(BenchMarkState state) {
state.treeMap.get(state.getKey());
}
@Benchmark
public void testHashMap(BenchMarkState state) {
state.hashMap.get(state.getKey());
}
public static void main(String[] args) throws RunnerException {
Options opt = new OptionsBuilder()
.include(JavaMapBenchmark.class.getSimpleName())
.forks(1)
.build();
new Runner(opt).run();
}
}
Я получил следующий результат:
Benchmark Mode Cnt Score Error Units
JavaMapBenchmark.testHashMap thrpt 5 16778578.614 ± 901741.764 ops/s
JavaMapBenchmark.testTreeMap thrpt 5 6345125.655 ± 335465.052 ops/s
Таким образом в моем случае get в HashMap быстрее чем в TreeMap.
Какие вопросы я оставил без ответа:
- State и как с ним правильно работать в бенчмарке
- Настройки запуски бенчмарка с помощью аннотаций
- Интерпретация результатов бенчмарка, что значат все эти Mode, Cnt, Score, Error, Units.