Kotlin으로 Eager evaluation, Lazy evaluation 쉽게 이해하기
이번 글에서는 eager evaluation과 lazy evaluation에 대해 알아보겠습니다.
이 글은 Kotlin 1.9.0을 기준으로 작성하였으며 참고 자료는 다음과 같습니다.
Eager evaluation
Eager evaluation은 변수나 함수가 호출될 때 바로 계산하는 처리 방식입니다.
장점
- 값을 바로 계산하기 때문에 코드의 흐름을 파악하기 쉽다.
- 어느 지점에서 오류가 발생했는지 디버깅하기 쉽다.
- 값을 계산할지 판단하는 overhead가 발생하지 않는다.
단점
- 작업에서 불필요한 데이터도 계산하여 자원 낭비가 발생한다.
- 무한 개의 데이터를 처리할 수 없다.
Lazy evaluation
Lazy evaluation은 값이 필요할 때까지 계산을 지연하는 처리 방식입니다. 장단점은 다음과 같습니다.
장점
- 불필요한 계산을 피할 수 있어 CPU와 메모리 자원을 아낄 수 있다.
- 값이 필요한 시점까지만 계산하므로 큰 데이터를 다룰 때 용이하고 무한개의 데이터도 다룰 수 있다.
단점
- 값이 필요할 때 계산되므로 디버깅에 어려움을 겪을 수 있다.
- 값이 필요한지 확인하는 과정에서 발생하는 overhead로 인해 작은 데이터를 다룰 때 느릴 수 있다.
Kotlin에서 확인하기
Kotlin의 Collection과 Sequence를 이용하면 두 방식의 처리 방법을 쉽게 확인할 수 있는데요. 각 자료형의 동작 방식은 다음과 같습니다.
- Collection: eager evaluation
- Sequence: lazy evaluation
그럼 1부터 10까지 정수 리스트가 주어질 때 짝수 3개 리스트를 구하는 코드를 보겠습니다.
internal class EvaluationTest : BehaviorSpec({
given("1부터 10까지 정수 리스트가 주어진다.") {
val nums = (1..10).toList()
`when`("Collection을 이용하여 짝수 3개를 필터링하면") {
val result = nums
.filter { println("filter target = $it"); it % 2 == 0 }
.onEach { println("filtered = $it") }
.take(3)
then("Eager evaluation으로 처리한다.") {
result shouldBe listOf(2, 4, 6)
}
}
`when`("Sequence를 이용하여 짝수 3개를 필터링하면") {
val result = nums.asSequence()
.filter { println("filter target = $it"); it % 2 == 0 }
.onEach { println("filtered = $it") }
.take(3)
.toList()
then("Lazy evaluation으로 처리한다.") {
result shouldBe listOf(2, 4, 6)
}
}
}
})
Collection의 경우
Eager evaluation으로 처리하는 Collection의 경우 각 단계에서 모든 값을 계산한 후 다음 단계로 넘어갑니다.
- 첫 번째 단계에서 계산한 값: 1, 2, 3, 4, 5, 6, 7, 8, 9, 10
- 두 번째 단계에서 계산한 값: 2, 4, 6, 8, 10
- 전체 개수: 15개
Sequence의 경우
Lazy evaluation으로 처리하는 Sequence의 경우 하나의 원소가 모든 단계를 거친 후 다음 원소를 처리합니다.
- 첫 번째 단계에서 계산한 값: 1, 2, 3, 4, 5, 6
- 두 번째 단계에서 계산한 값: 2, 4, 6
- 전체 개수: 9개
결과
똑같은 결과를 얻는데 있어 lazy evaluation이 eager evaluation보다 40% 효율적입니다.
마무리하며
이번 글에서는 eager evaluation과 lazy evaluation에 대해 알아보았습니다. Kotlin의 Collection과 Sequence를 이용하여 lazy evaluation의 효율을 두 눈으로 확인할 수 있었는데요. lazy evaluation는 처리해야하는 데이터가 크면 클수록 더 높은 효율을 보일 것입니다.
개인적으로 eager evaluation과 lazy evaluation을 이해하기 정말 어려웠는데요. 다행히 Kotlin의 Sequence의 존재를 알고 테스트 코드를 작성하니 쉽게 이해할 수 있었습니다. 아무래도 저는 학습 테스트로 공부하는게 가장 빨리 배우는 것 같네요. 😭
이번 글에서 사용한 코드는 이 곳에서 확인하실 수 있습니다.
댓글남기기