Backend/Kotlin

[Kotlin] inline

findmypiece 2021. 12. 6. 11:20
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(23) { 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(45, func))
}
cs

 

보면 알겠지만 Function 인터페이스를 구현한 객체를 생성해서 사용하고 있는 것을 확인할 수 있다. 이에 아래와 같이 testFunc를 여러번 호출해서 사용할 경우 그 만큼 객체가 생성되어 사용되기 떄문에 메모리 할당에 의한 런타임 오버헤드가 발생한다.

1
2
3
4
5
6
7
@Test
fun test() {
    println(testFunc(13) { a, b -> a + b})
    println(testFunc(13) { a, b -> a - b})
    println(testFunc(13) { a, b -> a * b})
    println(testFunc(13) { 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