I, Inline function
1, Vấn đề
- Trước khi đọc bài viết này, mình khuyên bạn nên đọc về high-order function trước.
- High-order function gặp vấn đề là mỗi parameter có function type cần được khởi tạo bằng 1
function object
trong memory và tạo ra runtime overhead. - Ví dụ 1:
1 | class InlineExample { |
- Khi chúng ta dùng xem nó được compile qua java code bằng
Tools > Kotlin > Show kotlin bytecode > Decompile
, chúng ta sẽ thấy classInlineExample.java
1 | public final class InlineExample { |
- Ta có thể thấy
makeHighOrder()
trongInlineExample.java
có 1 tham sốaction
có kiểuFunction0
. - Khi nó được sử dụng ở
testAnonymous()
vàtestLambada()
thì sẽ tạo ra 2 objectFunction0
. - Trong kotlin, chúng ta không tạo ra đối tượng nào cả ? Đây cũng là vấn đề của high-order function.
2, Inline function
- Ví dụ 2: tương tự như ví dụ 1 nhưng mình sẽ thêm
inline
keyword vào trướcmakeHighOrder()
1 | class InlineExample { |
- Khi đó, InlineExample sẽ được compile sang java code như sau
1 | public final class InlineExample { |
- Mặc dù
makeHighOrder()
vẫn được compile gần giống như cũ. - Nhưng khi gọi
testAnonymous()
vàtestLambada()
nhưng không tạo raFunction0
nào nữa. - Có chuyện gì xảy ra khi ta sử dụng inline function ?
- Từ khóa
inline
đã copy implement của function vào nơi gọi function (call-site) đó. Do đó các call-site không tạo ra bất cứ object nào. - Chú ý:
- Inline function được dùng để tối ưu cho high-order function.
- Nếu bạn thêm
inline
vào những function thông thường sẽ không có ý nghĩa về mặt tối ưu. Android studio sẽ có warning và suggest bạn bỏinline
đi.
1 | // No performance impact. We will get warning here |
3, Giới hạn và cách dùng inline function
- Nhược điểm của inline function mà chúng ta có thể thấy ngay là chúng có thể gây ra nhiều code thừa vì implement của nó có thể dùng ở nhiều nơi.
- Inline function dùng ở đâu ?
- Chúng ta nên tránh sử dụng
inline
cho những function lớn. Chúng ta nêninline
cho những function nhỏ (vài ba dòng). - Nếu bạn xem source code của file
_Collections.kt
thì bạn sẽ thấy các inline function chỉ có từ 1 đến 3 dòng.
II, Noinline
- Inline function không cho phép parameter có function type:
- Gán cho 1 local variable.
- Truyền vào trong function khác ở body.
- Ví dụ 3:
1 | private inline fun makeHighOrder( |
- Trong trường hợp này, chúng ta có thể đánh dấu
notInline
bằng từ khoánoinline
như ví dụ 4. - Ví dụ 4: sửa error ở ví dụ 3
1 | private inline fun makeHighOrder( |
- Khi sử dụng
noinline
cho biếnnotInline
thì khi khởi tạonotInline
lại tạo ra object trong bộ nhớ.