Options for getting function to Inline in Netmf?

G30
Netmf 4.3

Are there any options for replacing function calls with inline routines?

Apologies if I am messing up the terminology here… let me elaborate:

    public static void Update_Waiting()
    {
        SwitchReadings = GetFireModeFromSwitches();
    
        if(SwitchReadings != currentFireMode)
        {
            StartValidation(SwitchReadings);
        }
    }

    
    public static void Update_Validating()
    {
        SwitchReadings = GetFireModeFromSwitches();

        if(SwitchReadings != validationFireMode)
        {
            StartValidation(SwitchReadings);
        }

        else if((DateTime.Now - StartValidatingTime) > ValidationPeriod)
        {
            ...

Update_Waiting and Update_Validating essentially define the two states of this object. The main loop of the program will always be calling exactly one of these in each iteration.

These two functions have some overlapping tasks… such as GetFireModeFromSwitches().

I checked the IL and the function, GetFireModeFromSwitches is “called.”

I can significantly decrease execution time by making this, and other similar tasks inline, correct? How can I make it happen? (while maintaining good Not-Repeating-Myself practice)

By inline routines do you mean Anonymous Methods?

Googled…

May work…

@Mike. I unfortunately had already checked that out and found AgressiveInlining missing in Netmf. None of the other ones seem to be related except for “NoInlining” … I didn’t try it out but I assume it does precisely the opposite of what I want.

@Mr_John_Smith Perhaps I am looking for Anonymous Methods? I need to research this term.

To further clarify what I mean consider this:

Let’s say I have…

public void DoWork(int b, int c)
{
    int a = b + c;
}

and I’ll make up some IL-like language for this function:

load B;
load C;
add B, C, A;

And then I have another function,

public void DoWork_TheCallingFunction()
{
    DoWork(b, c);
}

As it stands the IL for DoWork_TheCallingFunction would be like this:

call DoWork;

But I want it to be like this

load B;
load C;
add B, C, A;

but why…
Telling that might actually get a better outcome

@Brett I want to see if it is faster. If it were to be faster than I can leverage it in many places in my program and I might find that my Main Program Update loop hits higher frequencies. And I have a target frequency that I have not hit yet.

The reason I think it will be faster is because it is to my knowledge always faster… even in native environments. It simply yields less instructions to execute no matter how you look at it.

There are examples of using the AgressiveInline MethodImplOption in the full .Net that bring some trivial example routine (just like the one I gave) down from 7.2 ns to 0.3 ns

I’m also recalling that the Netmf stack is built on the heap… which makes me think that function calls carry a significant overhead just in this regard.

I could be wrong… but I’m pretty sure this is a very common tactic in embedded programming which sacrifices code size for speed while maintaining readability of the source.

…where implemented. That in itself will be the Achilles Heel for many things in netmf - the goals were to cut the crap to the bare bones, to get on smaller micros. Which means features like this get cut, and you have to compromise. Not saying that this is bad, just saying your expectation that you have magic tweaks at your fingertips needs to be tempered :wink:

@Brett

Okay, and that’s fine. If that is the case then I have to decide: if I need the speed and can get it this way then it’s a matter of copy and pasting routines where I had created functions.

I just thought I’d reach out after i found AgressiveInlining option to be missing.

Are these mechanical switches that are being polled rather than using interrupts or something totally else?

@justin This routine I showed in my code in particular is polled switches.

So perhaps the interrupt system would help me get a nice increase in frequency of the loop. But there are other examples where inlining could help too and that have nothing to do with polling.

One thing that can show glaring performance hits is when the GC runs so if you havent then EnableGCMessages and see if you get lots GC messages.

I had this once reading mutiple i2c devices that was creating too many objects so lots of GC running - loop went from 115Hz to 1000Hz…

1 Like

I just did a quick test on my theory…

    private static void CountUp()
    {
        Count = Count + 1;
    }

    private static void MainLoop()
    {
        Start = DateTime.Now;
        while((DateTime.Now - Start) < Period)
        {
            CountUp();
        }
        Debug.Print("With Call: " + Count.ToString());

        Count = 0;
        Start = DateTime.Now;
        while((DateTime.Now - Start) < Period)
        {
            Count = Count + 1;
        }
        Debug.Print("Without Call: " + Count.ToString());

And the output:

With Call: 8734
Without Call: 10566

Interestingly when i run your code in 4.4 on a 411 in Main the difference for me is not as pronounced…

Period == 1000ms

With Call: 7216
Without Call: 7634

@Justin that is interesting.

I also tried increasing the amount of work done in the function. This also brought the gap closer together.

Stand by - its about to get more interesting…

Guys this is what RLP was meant to solve.

1 Like

Without any changes i now get

With Call: 10125
Without Call: 11181

do do do do

G30 == no-rlp

Any way… to sum up:

Function calls take time. If you want to avoid them you must be explicit. And that’s not a problem… it’s just the price we pay.

Ah right G30 was the very first thing he said.

If function calls take time, then try a goto statement.