JMH로 자바 성능측정 비교하기 - java performance

성능측정 과제

  • Map, Set, List, Queue 의 성능은 어떨지 알아보기
  • 실험을 통해 Map / List 성능 측정

JMH 기본적인 사용법 (시작하기)

아래와 같은 명령어를 사용해 maven project를 생성한다

1
2
3
4
5
6
7
mvn archetype:generate \
-DinteractiveMode=false \
-DarchetypeGroupId=org.openjdk.jmh \
-DarchetypeArtifactId=jmh-java-benchmark-archetype \
-DgroupId=org.sample \
-DartifactId=test \
-Dversion=1.0
  • 성능 측정 코드 작성 (아래에서 계속)
  • mvn clean install 로 빌드
  • java -jar target/benchmarks.jar 로 성능측정

Map, Set, List, Queue 차이점

위 4가지는 Java에서 사용 가능한 Collection이고 데이터를 모아서 사용한다는 점에서 비슷하지만 차이가 있다.

Map

Map<K,V> key 와 value 쌍으로 이루어져 있어서 두개의 값을 mapping 하는 용도로 많이 사용한다. 쉽게 생각하면 database에 attribute 가 1개밖에 없는 table이다. key 값을 넣으면 value 를 리턴해 준다. 개인적으로 구현체로는 주로 HashMap을 쓰며 , Map<String,String> = new HashMap<>() 처럼 사용

Set,List,Queue

이 3가지를 분리 한 이유는, 이 모두 Map과 다르게 쌍이 아닌 데이터 자체를 모으기 때문이다. 하지만 세부적인 기능은 다르다.

  • List
    • 순서가 있는 데이터를 저장 할 때 사용
    • 같은 값의 데이터가 들어와도 다른 index에 저장이 된다.
    • ArrayList, LinkedList..
  • Set
    • ‘집합’ 이라는 뜻을 가짐
    • 중복을 허용하지 않는다, 데이터를 넣을때 이미 같은 값을 저장하고 있는 경우 저장하지 않음
    • 출력 할때도 어떤 순서로 출력될지 모른다!
  • Queue

JMH 를 사용하여 List 추가/조회/삭제 성능측정

  • option :
    1
    2
    @BenchmarkMode(Mode.AverageTime)
    @OutputTimeUnit(TimeUnit.NANOSECONDS)

추가

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
@Benchmark
public void addIntoArrayList() {

List<String> arrayList = new ArrayList<>();
for (int i = 0; i < 100; i++) {
arrayList.add("Hello");
}
}

@Benchmark
public void addIntoLinkedList() {

List<String> linkedList = new LinkedList<>();
for (int i = 0; i < 100; i++) {
linkedList.add("Hello");
}
}

조회(랜덤)

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
@Benchmark
public void searchArrayList(State state) {

List<String> arrayList = state.arrayListForSearch;
int number = (int) (arrayList.size()%Math.random());
for (int i = 0; i < 100; i++) {
arrayList.get(number);
}
}

@Benchmark
public void searchLinkedList(State state) {

List<String> linkedList = state.LinkedListForSearch;
int number = (int) (linkedList.size()%Math.random());
for (int i = 0; i < 100; i++) {
linkedList.get(number);
}
}

삭제(랜덤값)

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
@Benchmark
public void deleteFromArrayList(State state) {

List<String> arrayList = new ArrayList(state.arrayListForSearch) ;
int number = (int) (Math.random()%arrayList.size());
for (int i = 0; i < 10; i++) {
arrayList.remove(number);
}
}

@Benchmark
public void deleteFromLinkedList(State state) {

List<String> linkedList = new ArrayList(state.LinkedListForSearch);
int number = (int) (Math.random()%linkedList.size());
for (int i = 0; i < 10; i++) {
linkedList.remove(number);
}
}

JMH 를 사용하여 Map 추가/조회/삭제 성능측정

추가

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
@Benchmark
public void addIntoHashMap() {

Map<String, String> hashMap = new HashMap<>();
for (int i = 0; i < 100; i++) {
hashMap.put(i + "", "Hello");
}
}

@Benchmark
public void addIntoTreeMap() {

Map<String, String> treeMap = new TreeMap<>();
for (int i = 0; i < 100; i++) {
treeMap.put(i + "", "Hello");
}
}

조회(랜덤)

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
@Benchmark
public void searchHashMap(State state) {

Map<String, String> hashMap = state.hashMapForSearch;
int number = (int) (Math.random()%hashMap.size());
for (int i = 0; i < 100; i++) {
hashMap.get(number + "");
}
}

@Benchmark
public void searchTreeMap(State state) {

Map<String, String> treeMap = new TreeMap<>();
int number = (int) (Math.random()%treeMap.size());
for (int i = 0; i < 100; i++) {
treeMap.get(number + "");
}
}

삭제(랜덤값)

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
@Benchmark
public void deleteFromHashMap(State state) {

Map<String, String> hashMap = new TreeMap(state.hashMapForSearch);
int number = (int) (Math.random()%hashMap.size());
for (int i = 0; i < 10; i++) {
hashMap.remove(number + "");
}
}

@Benchmark
public void deleteFromTreeMap(State state) {

Map<String, String> treeMap = new TreeMap(state.TreeMapForSearch);

for (int i = 0; i < 10; i++) {
int number = (int) (Math.random()%treeMap.size());
treeMap.remove(number + "");

}
}

참고 자료

Comments