Java 성능 시간 측정

GilLog·2021년 5월 3일
0

🙆‍♂️ import 🙇‍♂️

자바 성능 튜닝 이야기[ProgrammingInsight-이상민]


작성한 자신의 메소드의 성능을 측정하는 방법에는 여러가지가 존재한다.

이중 System Class에서 제공하는 static 시간 측정 메소드로 대표적인 currentTimeMilis()nanoTime() 메소드가 있다.

static long currentTimeMillis()

currentTimeMillis()는 현재 시간을 ms로 return한다.

UTC라는 시간 표준 체계를 따르며, 1970년 1월 1일 부터 시간을 long 타입으로 return한다.
대한민국은 UTC+9 지역이다.

따라서 호출 할 때마다 값이 다르다.

이 시간 값을 변환하여 현재 날짜를 구할 수도 있다.

static long nanoTime()

nanoTime()는 JDK 5.0부터 추가된 메소드이다.

현재 시간을 ns로 return한다.

1ms 이하의 nano 수행 시간 측정을 위해 만들어진 메소드오늘 날짜를 알아내는 부분에서는 사용하지 않고, 성능 측정 용도로 사용하는 메소드이다.


JMH

JMH는 Java Microbenchmark Harness의 약자로, JDK를 오픈 소스로 제공하는 OpenJDK에서 만든 Java 성능 측정용 라이브러리다.

이 외에도

Caliper, JUnitPerf, JUnitBench, ContiPerf등의 측정 라이브러리 들이 존재한다.

JMHCaliper를 제외한 나머지 Tool들은 JUnit 테스트 코드 실행에 사용된다.


아래 예제는 `JMH`로 HashMap과 ArrayList 객체 생성 속도를 비교해보는 예제이다.
package com.perf.timer;

import java.util.ArrayList;
import java.util.HashMap;
import java.util.concurrent.TimeUnit;

import org.openjdk.jmh.annotations.BenchmarkMode;
import org.openjdk.jmh.annotations.GenerateMicroBenchmark;
import org.openjdk.jmh.annotations.Mode;
import org.openjdk.jmh.annotations.OutputTimeUnit;

// JMH Class 선언 시 반드시 Annotation을 지정할 필요는 없지만, 이렇게 하면 기본 옵션으로 수행되기에 평균 응답 시간 측정을 위해 @BenchmarkMode로 옵션을 지정
@BenchmarkMode({ Mode.AverageTime })
// @OutputTimeUnit Annotation을 사용하여 출력 시간 단위를 밀리초로 지정, 기본 옵션이 밀리이지만 시간 단위를 옵션으로 명시할 수 있는 예시
@OutputTimeUnit(TimeUnit.MILLISECONDS)
public class CompareTimerJMH {

    // 측정 대상이 되는 메소드를 선언할 때 사용, 해당 클래스에 메소드가 많이 있어도 이 Annotation을 설정하지 않으면 테스트 대상 제외
    @GenerateMicroBenchmark
    public DummyData makeObject(){
        HashMap<String, String> map = new HashMap<String, String>(1000000);
        ArrayList<String> list = new ArrayList<String>(1000000);
        return new DummyData(map, list);
    }
}

아래는 JMH 테스트 실행 결과이다.

$ java -jar target/microbenchmarks.jar .*CompareTimerJMH.* -i 3 -r 1s
# Measurement Section
# Runtime (Per iteration): 1s
# Iterations: 3
# Thread counts (concurrent threads per iteration): [1, 1, 1]
# Threads will synchronize iterations
# Benchmark mode: Average time, time/op
# Running: com.perf.timer.CompareTimerJMH.makeObjectWithSize1000000
# Warmup Iteration	1 (3s in 1 thread): 2.691 msec/op
# Warmup Iteration	2 (3s in 1 thread): 2.131 msec/op
# Warmup Iteration	3 (3s in 1 thread): 2.317 msec/op
# Warmup Iteration	4 (3s in 1 thread): 2.172 msec/op
# Warmup Iteration	5 (3s in 1 thread): 2.134 msec/op
Iteartion	1 (1s in 1 thread): 2.011 msec/op
Iteartion	2 (1s in 1 thread): 2.215 msec/op
Iteartion	3 (1s in 1 thread): 2.311 msec/op

Run result "makeObjectWithSize1000000": 2.089 ±(95%) 0.160 ±(99%) 0.369 msec/op
Run statics "makeObject": min = 2.011, avg = 2.114, max = 2.311, stdev = 0.057
Run confidence intervals "makeObjectWithSize1000000": 95% [1.929, 2.249], 99% [1.720, 2.458]

Benchmark			Mode	Thr	Cnt	Sec	Mean	Mean	error	Units
c.p.t.CompareTimerJMH.makeObject avgt	1	3	1	2.098	0.369 msce/op

위 처럼 JMH는 여러개 스레드 단위 테스트도 가능하고, 워밍업 작업도 자동 수행하기에 정확한 성능 측정이 가능하다.

profile
🚀 기록보단 길록을 20.10 ~ 22.02 ⭐ Move To : https://gil-log.github.io/

0개의 댓글