To Inline or Not to Inline.. that is the question


#1

So..
Could anyone outline the circumstances when there's a benefit to be had in using compiler directives to force inlining of functions, when there isn't, and when not to specify either way?

My suspicion is that inlining is only of benefit for smaller/less complex functions. Then again, I'm vague on what inlining actually does. I assume it copies the function inline each time it is called, rather than actually invoking the function from another location in RAM, passing arguments, retrieving the return value etc.. If that's the case I imagine there comes a point where the RAM overhead of complex functions being inlined multiple times outweighs the speed advantage of inlining, but as I said, I'm generally vague on these matters...

a|x


#2

You have the right understanding. It's basically copying the body of a function to where it would've inserted a call, and as you say, it makes the code longer unless your function is just one instruction, but it does save some theoretical overhead.

It can make a big difference in some cases but function calls really aren't very expensive on ARM. If you have one-two line functions in your objects, or if the main loop is split into simple calls to two-three functions for clarity but they aren't used elsewhere, by all means mark them inline to save a few cycles. But don't expect miracles :slight_smile:

(Also, if GCC is compiling the firmware with optimizations on (don't know if it does), you might already be getting the most obvious cases inlined.)


#3

a note:
with the optimisation levels we use if you included functions within the same compile unit, the compiler will want to inline them... this is is likely to be the case in object dev, since you tend to include them, as currently we do not provide a mechanism to add other files to be compiled as separate units.

the issue, as rvense points out, this can lead to severe code bloat, this is why in my push object you will see I've disabled inlining explicitly on many functions that are large, and also infrequently called.

personally, I think at some point we will need to allow for different compilation units within axoloti, to gain a bit more control over this optimisation, but its tricky to do whilst retaining simplicity for the end user.


#4

Does a compile unit equate to an individual object, generally-speaking?

I was wondering about global variables, actually, maybe this is related. I know the use of globals is generally frowned upon in desktop computer programming these days, but all the factory objects use them, so it occurred to me that perhaps objects are encapsulated in some way at compile-time, so what appear to be global variables are actually only scoped to the object that contains them. This would make a lot of sense, in terms of having multiple instances of the same object operating independently in the same patch, without explicit encapsulation in C++ class/instances.

a|x


#5

no, a compile unit is a C file... and given a patch contents all ends up in xpatch.cpp, its all one compile unit. (hence my 'warning')

in programming there are various reasons for 'global' being bad, but like all things, it depends...
class scoping a global (static) is neither good nor bad, it depends how you use it, and even the most fervent object oriented programmers have used singletons which are still essentially a global, albeit alleviating some of the negatives of globals.
but yeah, generally, you avoid globals with objects as you don't wont one object instance to affect another.

also, be careful with Axoloti , axoloti objects are not classes... e.g. each instance of an object becomes a class.
generally, its a good idea to check out xpatch.cpp,

Ive probably mentioned this in the past, and you may be doing this , but I recommend when you get to the level of creating custom objects, its a good time to start looking at the generated code, to get a better understanding of axoloti. create a very simple patch, compile it and then look at xpatch.cpp and get a good feeling of how the 2 related, and how it works.
Of course this is not 'required', but I personally learnt a lot from this... and even now, when a patch doesnt work, it can be instructive to go look at the code thats be generated , to see why.

tip: a good code editor and 'code beautifier' is useful to navigate through it.

advance tip: when your developing objects, and trying to fix build issues, if you have expert mode on, you can edit the xpatch.cpp and then just compile to try stuff quickly (e.g. to fix compile errors), then apply to your custom object when you know it works.