자바 EnumMap vs HashMap 성능 비교

자바 EnumMap vs HashMap 성능 비교

이번 우테코 로또 미션 진행중에 EnumMap을 사용하게 되어서 성능을 테스트 해보았다

EnumMapHashMap에 비해서 굉장히 빨랐다

또 혼자서 한번 벤치마크 테스터기를 만들어서 간단히 실행을 진행해보았다

대략적인 설계도

image

정확한 UML 이 절대로 아니다 !! 특히 화살표!

아이디어는 프록시 패턴에서 얻었다 다만 내부적인 캐싱은 하고 있지 않다 (그저 생성자로 DI만 함)

public class Main {
    public static void main(final String... args) {
        MyBenchMark benchMark = new EnumMapClass();
//        MyBenchMark benchMark = new HashMapClass();

        MyBenchMarkRunner benchMarkRunner = new MyBenchMarkRunner(benchMark);
        benchMarkRunner.run();
    }
}
public class MyBenchMarkRunner {

    private final MyBenchMark benchMark;

    private static final int NUMBER_OF_REPETITIONS = 10;

    public MyBenchMarkRunner(MyBenchMark benchMark) {
        this.benchMark = benchMark;
    }

    public void run() {
        long resultSum = 0L;
        try {
            for (int i = 0; i < NUMBER_OF_REPETITIONS; i++) {
                long start = System.currentTimeMillis();
                benchMark.test();
                long elapsedTime = System.currentTimeMillis() - start;
                out.printf("elapsedTime :  %d ms \n", elapsedTime);
                resultSum += elapsedTime;
            }
        } catch (RuntimeException e) {
            out.println(e.getMessage());
        }
        double avgTime = (double) resultSum / NUMBER_OF_REPETITIONS;
        out.printf("\n %d회 반복 평균 시간 :  %.2f ms \n", NUMBER_OF_REPETITIONS, avgTime);
    }

}
public interface MyBenchMark {
    int NUMBER_OF_TRIALS = 10_000_000;
    void test() throws RuntimeException;
}
public class EnumMapClass implements MyBenchMark {

    private EnumMap<MyEnum, Integer> map;

    public EnumMapClass() {
        map = new EnumMap<>(MyEnum.class);
        for (MyEnum value : MyEnum.values()) {
            map.put(value, value.num);
        }
    }

    @Override
    public void test() throws RuntimeException {
        final int myEnumSize = MyEnum.values().length;
        for (int i = 0; i < NUMBER_OF_TRIALS / myEnumSize; i++) {
            for (MyEnum value : MyEnum.values()) {
                map.get(value);
            }
        }
    }

    @RequiredArgsConstructor
    private enum MyEnum {
        N1(1), N2(2), N3(3), N4(4), N5(5), N6(6), N7(7), N8(8), N9(9), N10(10);
        private final int num;
    }
}
public class HashMapClass implements MyBenchMark {

    private Map<Integer, Integer> map;

    public HashMapClass() {
        map = new HashMap<>();
        IntStream.rangeClosed(1, NUMBER_OF_TRIALS).forEach(value -> map.put(value, value));
    }

    @Override
    public void test() {
        map();
    }

    private void map() {
        IntStream.rangeClosed(1, NUMBER_OF_TRIALS).forEach(value -> map.get(value));
    }
}

실험 개요

HashMap 에는 천만 개의 숫자를 넣고 1부터 천만까지 순회하면서 찾았다

EnumMap은 우선 열 개의 인스턴스를 갖는 Enum을 내부 클래스에 정의하여 백만회 순회하면서 검색을 하였다

그러니까 각각 모두 천만번 검색을 한 것!

실험결과

  1. HashMap

image

  1. EnumMap

image


결론

EnumMap이 10.9 배 빨랐다

내부적으로 해싱을 하지 않고 ordinal을 이용 + 배열로 구현되어 있어서 그런지 굉장히 빨랐다




© 2020.12. by 따라쟁이

Powered by philz