수행 시간 측정
val startTime = getCurrentTime()
// do something
val endTime = getCurrentTime()
println("elapsedTime : ${endTime - startTime}")
일반적으로 성능을 측정할때는 어떤 기능을 수행하는데 걸리는 시간을 측정합니다. 위 코드는 어떤 기능을 수행하는데 소요된 시간을 보여줍니다.
Java
Java에서는 시스템의 시간을 가져오는데 기본적으로 System.currentTimeMillis()
, System.nanoTime()
을 제공합니다.
System.currentTimeMillis()
System.currentTimeMillis()
은 1970/1/1 00:00:00 UTC
을 기준으로 현재 시간을 리턴합니다. 시스템의 TimeZone에 관계없이 항상 UTC 시간을 리턴하기 때문에 보통 "Unix time", "epoch time"이라고 부릅니다.
System.nanoTime()
System.nanoTime()
은 로컬 시스템에서 가장 정확한 현재 timestamp를 나노초 단위로 리턴합니다. (리눅스의 CLOCK_MONOTONIC
과 같습니다) 정확한 현재 시간을 나타내는건 아니므로, 시간을 측정할때만 사용되어야 하며, 같은 프로세스, 같은 디바이스 간의 timestamp와 비교하여야 합니다. 현재 시간을 알고 싶으면 System.currentTimeMillis()
을 사용해야 합니다.
Kotlin
코틀린에서는 시간 측정을 보다 간편하게 할 수 있도록 몇가지 함수를 제공합니다.
measureTimeMillis(block: () -> Unit): Long
위의 Java에서 설명한 System.currentTimeMillis()
사용하여 block 을 실행하는데 소요된 시간을 Long
형식으로 반환 합니다.
val elapsed: Long = measureTimeMillis {
Thread.sleep(100)
}
println(elapsed)
measureNanoTime(block: () -> Unit): Long
위의 Java에서 설명한 System.nanoTime()
사용하여 block 을 실행하는데 소요된 시간을 Long
형식으로 반환 합니다.
val elapsed: Long = measureNanoTime {
Thread.sleep(100)
}
println(elapsed)
위 두 함수를 이용하면 이전보다 더 편하게 시간을 측정 할 수 있지만, block 내에서 실행된 값을 얻어 오기 불편하다는 단점이 있습니다.
이땐 kotlin 1.3에서 experimental로 추가된 함수를 이용 할 수 있습니다.
measureTimedValue(block: () -> T): TimedValue
val timedValue: TimedValue<User> = measureTimedValue {
service.getUser()
}
val duration: Duration = timedValue.duration
val user: User = timedValue.value
measureTimedValue
은 블록에 소요된 시간만 Long
으로 반환 하는 대신, TimedValue
라는 클래스를 통해 block의 결과값과 시간을 함께 반환합니다.
measureTime(block: () -> Unit): Duration
val duration: Duration = measureTimedValue {
Thread.sleep(100)
}
println(duration)
measureTime
은 위에 설명한 measureTimeMillis
와 같이 블록에 소요된 시간만 반환하지만, milliseoncd 단위가 아닌 Duration
이라는 클래스로 반환합니다.
Duration
kotlin 1.3에서 experimental로 추가된 클래스입니다.
println("elapsed: ${duration.inSeconds}")
println("elapsed: ${duration.inMilliseconds}")
println("elapsed: $duration") // elapsed: 35.8us
위와 같이 seconds, milliseconds로(Double) 쉽게 변환 할 수 있고, toString()을 하게 되면 적당한 단위를 골라서 변환합니다.
val duration1 = 3600.toDuration(DurationUnit.SECONDS)
println(duration1) // => 60.0m
val duration2 = 0.5.toDuration(DurationUnit.HOURS)
println(duration1 + duration2) // => 90.0m
위와 같이 duration을 직접 만들 수 있으며, 합치거나 뺄 수 있습니다.
위의 모든 메소드에서 리턴값이 밀리초, 나노초 단위여도 그정도 수준의 정확도를 보장하는것은 아닙니다.
요약
- 수행 시간 측정을 편하게 하려면, kotlin 1.3에 추가된
measureTimedValue
을 이용하면 된다.
주의 사항
kotlin.system.measureTimeMillis
은 1.3.50기준 JVM, Native에서만 동작. (JavaScript는 불가능)kotlin.time.measureTimedValue
은 experimental이므로 API가 변경 될 수 있음. (JavaScript도 사용 가능)