728x90
고차함수는 다른 함수를 인자로 받거나 함수를 반환하는 함수이다. 코틀린에서는 람다나 함수 참조를 사용해 함수를 값으로 표현할 수 있다. 그런데 내부적으로 이게 실제로 사용될 때 내부적으로 Function 이라는 인터페이스를 구현한 객체를 생성해서 사용하게 된다.
예를 들어 아래와 같은 코드가 있다면
1
2
3
4
5
6
7
8
|
fun testFunc(a: Int, b: Int, body: (Int, Int) -> Int): Int {
return body(a, b)
}
@Test
fun test() {
println(testFunc(2, 3) { a, b -> a + b })
}
|
cs |
컴파일 단계에서 아래와 같이 변환된다.
1
2
3
4
5
6
7
8
9
|
fun testFunc(a: Int, b: Int, body: (Int, Int) -> Int): Int {
return body.invoke(a, b)
}
@Test
fun test() {
val func : Function<Int, Int, Int> = { a, b -> a + b }
println(testFunc(4, 5, func))
}
|
cs |
보면 알겠지만 Function 인터페이스를 구현한 객체를 생성해서 사용하고 있는 것을 확인할 수 있다. 이에 아래와 같이 testFunc를 여러번 호출해서 사용할 경우 그 만큼 객체가 생성되어 사용되기 떄문에 메모리 할당에 의한 런타임 오버헤드가 발생한다.
1
2
3
4
5
6
7
|
@Test
fun test() {
println(testFunc(1, 3) { a, b -> a + b})
println(testFunc(1, 3) { a, b -> a - b})
println(testFunc(1, 3) { a, b -> a * b})
println(testFunc(1, 3) { a, b -> a / b})
}
|
cs |
이러한 문제를 해결하기 위해 코틀린에서 inline 키워드가 제공된다. 이를 사용할 경우 객체가 생성되는 것이 아니라 아래와 같이 body에 해당하는 람다가 자체가 복사되는 방식으로 컴파일 된다.
1
2
3
4
5
6
7
8
9
10
11
12
|
inline fun testFunc(a: Int, b: Int, body: (Int, Int) -> Int): Int {
return body(a, b)
}
@Test
fun test() {
println(4 + 5)
println(4 - 5)
println(4 * 5)
println(4 / 5)
}
|
cs |
그렇다면 고차함수는 무조건 inline 키워드를 사용하는 게 좋은가? 꼭 그렇지는 않다. 많은 코드를 갖고 있는 함수를 inline 처리하면 바이트코드의 양이 훨씬 많아지게 된다. 이 경우 성능이 오히려 악화될 수도 있다. 따라서 inline 처리는 1~3라인 정도의 길이를 가지고 있는 함수가 권장하고 있다.
https://velog.io/@haero_kim/Kotlin-Inline-Function-파헤치기
https://sabarada.tistory.com/176
https://jcchu.medium.com/kotlin-inline-reified-알아보기-6880725a8cdf
728x90
'Backend > Kotlin' 카테고리의 다른 글
[Kotlin] interface default method (0) | 2021.12.22 |
---|---|
[Kotlin] 제네릭(내가 필요한 것만 정리..) (0) | 2021.12.06 |
[Kotlin] 코틀린에서 유틸함수 만들기 (0) | 2021.11.24 |
[Kotlin] val, const val (0) | 2021.11.22 |
[Kotlin] companion object (0) | 2021.11.22 |