inline

reified

modifier keyword

crossinline

inline


문서에는 다음과 같이 설명되어 있다.

고차 함수를 사용하면 런타임 패널티가 부과된다(impose(~을 부과하다)). 각 function은 객체이고, 그것은 closure, i.e.(다시 말해서, 즉 - 강조의 의미) function의 body 에서 엑세스된 변수를 캡처한다. 메모리 할당(function objects 와 classes 둘다)과 가상 call은 런타임 오베헤드를 초래한다(introduce). 그러나 많은 경우에 오버헤드의 이런 종류는 람다 표현에 inlining함으로써 제거할 수 있다. 아래에서 보여주는 functions은 이러한 상황의 좋은 예제이다. 즉, calculator() function은 쉽게 inline될 수 있다.

→ 즉, 런타임 오버헤드를 제거하기 위한 함수

위 코드는 컴파일 단계에서 아래와 비슷한 코드로 변환된다.

코틀린은 compile 단계에서 함수 타입의 변수, 즉 람다를 FunctionN 인터페이스를 구현한 "Object"로 저장한다. 코틀린 표준 라이브러리는 매개 변수에 따라 Function0<R>, Function1<P1, R>, Function2<P1, P2, R>... 인터페이스를 제공하고 각 매개변수 개수에 맞는 invoke() 메서드가 하나씩 선언되어 있다. 컴파일러는 FunctionN 인터페이스의 invoke() 메서드 내에 람다 식을 구현하고 해당 객체를 파라미터로 사용하는 것이다.

즉, testCalculator()에서 매개 변수로 전달한 "{a: Int, b: Int → a+b}" 람다 식은 매개변수가 두 개 이므로, Function2<Int, Int, Int> 인터페이스를 구현한 임의의 객체로 생성되어 calculator()의 body 매개 변수에 전달된다.

만일 위처럼 calculator() 함수를 각각 다른 람다 식을 사용해 여러 번 실행할 경우 람다 식마다 각각의 "객체"가 생성되어 메모리에 저장되고 해당 객체의 invoke() 함수가 각각 호출되기 때문에, 메모리 할당과 가상 호출에 의한 런타임 오버헤드가 발생하게 된다!!!! 헐...?

그래서 람다를 매개 변수로 사용하는 고차 함수를 "인라인 함수(Inline function)"으로 정의하여 오버 헤드를 줄일 수 있는 방법을 제공하고 있다.