I would like to know, if it is a good idea to inline small, private functions?
These functions, in my case, are only there for readability purposes and I know, that they are only called a few times, so the bigger bytecode size is insignificant.
I know, that the performance boost may also be insignificant, because I am not passing functional types (and the compiler actually warns me about that), but lets assume that it is a hot spot in our application.
Actual example:
I hava a theoretically infinite tape of symbols (like the one of a turing machine) which is modeled by tow arrays (left and right for positions < 0 and positions >= 0, respectively). Now I have read and write operations which are assumed to be called a lot.
In java I had:
/**
* @param cell the cell
* @return the symbol at the specified cell
*/
public char read(int cell) {
char[] tape;
if (cell < 0) {
tape = left;
cell = -cell - 1;
} else {
tape = right;
}
return cell < tape.length ? tape[cell] : blank;
}
/**
* Writes a symbol to the specified cell.
* @param c the symbol
* @param cell the cell
*/
public void write(char c, int cell) {
char[] tape;
if (cell < 0) {
cell = -cell - 1;
if (cell >= left.length) left = expandArray(left, cell, blank);
tape = left;
} else {
if (cell >= right.length) right = expandArray(right, cell, blank);
tape = right;
}
tape[cell] = c;
}
Now I wanted to translate the snippet to kotlin, read about inline functions and come up with this:
fun read(cell: Int = headPosition) = when {
cell < 0 -> read(left, -cell - 1)
else -> read(right, cell)
}
private inline fun read(tape: CharArray, cell: Int): Char {
return if (cell < tape.size) tape[cell] else blank
}
fun write(c: Char, cell: Int = headPosition) = when {
cell < 0 -> left = write(c, left, -cell - 1)
else -> right = write(c, right, cell)
}
private inline fun write(c: Char, tape: CharArray, cell: Int): CharArray = when {
cell >= tape.size -> expandArray(tape, cell, blank)
else -> tape
}.also { it[cell] = c }
I personally think, especially the read functions, are easy to read.
So is this a good idea and can I ignore the warning of the IDE? Or am I missing something? Maybe there is a best practice or other pattern to write these functions without repeading (almost) the same lines twice (for position < 0 and position >= 0).
Inline function instruct compiler to insert complete body of the function wherever that function got used in the code. Advantages of inline function are as follows: Function call overhead doesn't occur. It also saves the overhead of push/pop variables on the stack when the function is called.
The __inline keyword causes a function to be inlined only if you specify the optimize option. If optimize is specified, whether or not __inline is honored depends on the setting of the inline optimizer option. By default, the inline option is in effect whenever the optimizer is run.
Inline function and classes: If you need to explicitly declare inline function in the class then just declare the function inside the class and define it outside the class using inline keyword. };
There is no need to inline a very small repeatedly used function since the JVM JIT will likely do this for you anyway when it deems it to be appropriate. If you inline the function you do cause a bit of bloat in the generated bytecode but otherwise, there isn't a lot of harm there either for functions that are not called from many different points in your code. Bytecode bloat is worse for larger inline functions, functions used from many places in your code, and inline functions that call other inline functions. Your case does not cause much at all.
Short methods benefit heavily from inlining and as you can read in When Short Methods Pay Off: JIT Inlining:
A method is eligible for inlining if:
- It’s small – the bytecode size is smaller than 35 bytes (can be overridden by the -XX:MaxInlineSize=X flag).
- It’s called frequently (it’s hot) and it’s smaller than 325 bytes (can be overridden by the -XX:MaxFreqInlineSize=X flag).
If you exceed these parameters or want to pre-warm up the inlining you can use the inline
keyword to cause it to happen at compilation time.
You also would want to use inline
on small functions when:
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With