RSS

Tag Archives: Netduino

Micro-JSON for Netduino (and PC)

JSON logoThis is a pretty useful tool for the Netduino, which I need for playing around some Micro-WPF demo on the Eve board.
As soon you want to deal with web-services, JSON is a must-have format for serializing data. Although Netduino does not use Javascript, the JSON format is very compact, at least when compared to XML. By the way, XML is richer as structure and schema, and JSON is sometimes blurry about the data format (e.g. date and time).
The small software library comes with both a parser and a serializer. The parser rules strictly rely on the specification as in the official JSON portal.
The parser deserializes a JSON string to a DOM of specific objects. I’ve been deeply inspired by the JLinq of the awesome library JSON.Net by James Newton-King.

The problem.

Create a JSON parser isn’t a really complex task, unless you have to work on very-low resources devices. In that case, everything should be optimized at best.
My first attempt to create a decent parser and serializer was successful, but the result was not what I’d expected. Although the code runs surprisingly fast on a normal PC, on the Netduino Plus 2 runs pretty slow and takes a lot (i.e. too much) RAM. That leaded me to adjust and optimized several parts of the code, at least to solve the memory occupation issue. The second release is pretty better.

How it works.

The approach is functional-like, although it’s normal C# highly optimized for low-resources platform. However, the same code works on any .Net platform without any problem.
As stated, the first attempt wasn’t the best one. I used several resource-heavy components, which de-facto prohibits the usage on the Netduino. So, it turned to a different yet trivial solution using as less resources as possible. Not sure that’s the very best achievement possible, though.

For instance, here is the piece of code to parse a JSON string, as used in the first release:

        private static JsonParserContext ConsumeString(
            this JsonParserContext ctx,
            bool throws
            )
        {
            var src = ctx.Source;
            JsonParserContext rtn;
            if ((rtn = ctx.ConsumeWhiteSpace().ConsumeAnyChar("\"", throws)).IsSucceeded)
            {
                var sb = new StringBuilder();

                for (int p = src.Position, len = src.Text.Length; p < len; p++)
                {
                    char c;
                    if ((c = src.Text[p]) == '"')
                    {
                        src.Position = p + 1;
                        break;
                    }
                    else
                    {
                        sb.Append(c);
                    }
                }

                rtn.SetResult(
                    new JValue { BoxedValue = sb.ToString() }
                    );
            }

            return rtn;
        }

Below is how it is the new improved version. Notice that there’s no more the StringBuilder object, and it avoids the creation of new JsonParserContext instances on every call.

        private static JsonParserContext ConsumeString(
            this JsonParserContext ctx,
            bool throws
            )
        {
            if (ctx.ConsumeWhiteSpace().ConsumeAnyChar("\"", throws).IsSucceeded)
            {
                JSonReader src = ctx.Begin();

                for (int p = src.Position, len = src.Text.Length; p < len; p++)
                {
                    if ((src.Text[p]) == '"')
                    {
                        ctx.SetResult(
                            new JValue { BoxedValue = src.Text.Substring(src.Position, p - src.Position) }
                            );

                        src.Position = p + 1;
                        break;
                    }
                }
            }

            return ctx;
        }

Another great improvement (in terms of resource savings) is about the way to store the key-value pairs in a JSON object.
The first attempt uses the Hashtable object, which comes with any .Net platform, and it’s tailored for such purpose. However, its O(1)-access ability comes with a price in terms of resources, and it’s too high to afford for a Netduino.
The more-trivial solution of a simple array requires much less resources, but the data access now takes O(N).

Performance.

I performed the test with several JSON strings. The longest is about 9kiB, while the shortest is roughly 500 bytes.
Using the first release, the longest string is almost impossible to parse: the parser runs out of RAM very quickly.

Here are some results.
In the following picture there is the complete JSON “roundtrip” (parsing+serializing) of the shortest string (about 500 bytes), using the FIRST release.
The upper plot shows the parsing duration (high level) and takes about 170ms to complete. The serialization of the resulting object is way faster and requires a little more than 20ms (lower plot).

UNIT0000

Hereinafter, the charts are all related to the SECOND library release.
Here is the same 500 bytes-string parsed then serialized. Despite on the PC the revision takes a little longer to perform, on the Netduino is a little faster instead. I suppose all the benefits derive from the less RAM usage.

UNIT0001

Here is a 2kiB-JSON parsed, which takes almost 1.2 seconds to perform. The serialzation is not shown here.

UNIT0003

Finally, the “huge” 9kiB-JSON taking looooong to parse: almost 25 seconds!!!. There’s no serialization in this chart, because after a while the Netduino runs out of RAM. I believe there’s something to trim yet…

UNIT0002

The J-DOM.

I don’t know how to call it. The reference JSON.Net library where I inspired from offers a complete DOM support together with Linq, but that’s not possible in a tiny context as the Micro Framework is. By the way, the DOM I defined is JSON-specific: is the result of the serialization, and allows to manipulate the resulting object with ease. Once the DOM is complete, you can serialize it to have back a JSON string.
As stated, a must-have tool for any web-related application.

The usage is very simple and it’s the same as the JSON.Net’s JLinq (except for the Linq!).
Given this sample JSON string (as from Wikipedia):

{
    "firstName": "John",
    "lastName": "Smith",
    "age": 25,
    "address": {
        "streetAddress": "21 2nd Street",
        "city": "New York",
        "state": "NY",
        "postalCode": 10021
    },
    "phoneNumbers": [
        {
            "type": "home",
            "number": "212 555-1234"
        },
        {
            "type": "fax",
            "number": "646 555-4567"
        }
    ]
}

Here is some example of manipulation from within your C# code:

            var jdom = (JObject)JsonHelpers.Parse(s);

            Console.WriteLine((int)jdom["age"]);    //displays 25

            //add a new phone entry
            var jentry = new JObject();
            jentry["type"] = "mobile";
            jentry["number"] = "+39-123-456-7890";

            var jphones = (JArray)jdom["phoneNumbers"];
            jphones.Add(jentry);

            string jtxt = JsonHelpers.Serialize(jdom);
            Console.WriteLine(jtxt);

Okay, take me to the source code…

Here is the link with two complete Visual Studio solutions: both regular .Net and Netduino MF. The source contains also the first release of the parser, although it is not used.

 
1 Comment

Posted by on March 6, 2014 in .Net, Software

 

Tags: , , ,

Netduino + FT800 Eve = MicroWPF

The spare time is few, but step by step the target is getting closer.
It’s a been I’ve started playing around the FTDI FT800 Eve board, and it must admit it is awesome. If you need a quick solution to add a small touch display to your *duino board, the Eve is something you should consider.

EVE image

You know, I love Netduino and C#. That’s because I chose to play with the display using Netduino (Plus 2), and honestly I’d expected a pretty bad performance. Instead, the graphic engine of the Eve can be easily driven via SPI from any board. That is, the SPI on Netduino is fast, very fast.

My goal is creating a small library for helping many users to create small and funny home/hobby projects with the Netduino and the Eve display boards. Since I love the classic WPF, how could I avoid to inspire from them?

Micro WPF

If you know WPF, many concepts would come easier. Otherwise, I recommend to take a look to the documentation, tutorials and whatever you want. Even if you don’t harm with a PC, rather with the Windows Store/Phone APIs, the approach here isn’t too far from.
The “WPF” term for a simple Netduino is clearly abused. Here is just the visual approach, the XAML-like approach to create the UI, and -yes- the same ability to create your own controls: MeasureOverride and ArrangeOverride.
That’s not all.
If you have any visual application in mind with Netduino+Eve (e.g. a climate control, IoT client, etc), then probably you’d need some kind of navigation service across several pages. That’s the most modern UI experience, on every device: PC, tablets, and phones.

I still don’t write what the library will offer, because it’s just something made for fun: for helping hobbists and even students working with a UI on a such small board as Netduino is.
For sure, there are NOT (nor in the future):

  • data binding
  • XAML parsing (the tree has to be created programmatically)
  • styling
  • the remaining 99.99% of regular WPF…

An example of layout

The most versatile yet complex layout control is the Grid, but it seems working fine.
Let’s take this sample XAML:

<Page x:Class="WpfApplication2.Page1"
      xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
      xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
      xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006" 
      xmlns:d="http://schemas.microsoft.com/expression/blend/2008" 
      mc:Ignorable="d" 
      d:DesignHeight="300" d:DesignWidth="300"
	Title="Page1">

    <Grid>
        <Grid.ColumnDefinitions>
            <ColumnDefinition Width="150" />
            <ColumnDefinition Width="*" />
            <ColumnDefinition Width="Auto" />
        </Grid.ColumnDefinitions>

        <Grid.RowDefinitions>
            <RowDefinition Height="*" />
            <RowDefinition Height="2*" />
            <RowDefinition Height="Auto" />
        </Grid.RowDefinitions>

        <StackPanel
            Grid.Row="0"
            Grid.Column="0"
            x:Name="R0C0"
            Background="Blue"
            />

        <StackPanel
            Grid.Row="0"
            Grid.Column="1"
            x:Name="R0C1"
            Background="DarkGreen"
            />

        <StackPanel
            Grid.Row="0"
            Grid.Column="2"
            x:Name="R0C2"
            Background="Red"
            >
            <Button
                Content="Caption"
                Width="120"
                Height="30"
                Margin="10,5"
                HorizontalAlignment="Center"
                x:Name="B0"
                />
        </StackPanel>


        <StackPanel
            Grid.Row="1"
            Grid.Column="0"
            Grid.ColumnSpan="2"
            x:Name="R1C0"
            Background="LightPink"
            />


        <StackPanel
            Grid.Row="2"
            Grid.Column="1"
            Grid.ColumnSpan="2"
            x:Name="R2C1"
            Background="MediumSlateBlue"
            >
            <Button
                Content="Caption"
                Width="120"
                Height="30"
                Margin="10,5"
                HorizontalAlignment="Center"
                x:Name="B2"
                />
        </StackPanel>

    </Grid>
</Page>

On the regular WPF the result is the following:

sample-wpf

Now, let’s see how to write the same thing on Netduino:

    public class DemoPage2 : PageBase
    {
        protected override void OnCreate(FT800Device dc)
        {
            var btn_prev = new WidgetButton() { Margin = new Thickness(10, 5), Text = "Prev" };
            btn_prev.Click += new EventHandler(btn_prev_Click);

            var btn_next = new WidgetButton() { Margin = new Thickness(10, 5), Text = "Next" };
            btn_next.Click += new EventHandler(btn_next_Click);
            btn_next.HAlign = HorizontalAlignment.Center;

            var grid = new WidgetGridContainer();
            grid.Name = "GRID";

            grid.AddColumnDefinition(150);
            grid.AddColumnDefinition(1, GridUnitType.Star);
            grid.AddColumnDefinition(1, GridUnitType.Auto);

            grid.AddRowDefinition(1, GridUnitType.Star);
            grid.AddRowDefinition(2, GridUnitType.Star);
            grid.AddRowDefinition(1, GridUnitType.Auto);

            {
                var ctr = new WidgetStackContainer();
                ctr.Name = "R0C0";
                ctr.Background = Colors.Blue;
                grid.SetRowCol(ctr, 0, 0);
                grid.Children.Add(ctr);

                ctr.Children.Add(btn_prev);
            }
            {
                var ctr = new WidgetStackContainer();
                ctr.Name = "R0C1";
                ctr.Background = Colors.DarkGreen;
                grid.SetRowCol(ctr, 0, 1);
                grid.Children.Add(ctr);
            }
            {
                var ctr = new WidgetStackContainer();
                ctr.Name = "R0C2";
                ctr.Background = Colors.Red;
                grid.SetRowCol(ctr, 0, 2);
                grid.Children.Add(ctr);

                ctr.Children.Add(
                    new WidgetButton() { Name = "B0", Margin = new Thickness(10, 5) }
                    );
            }
            {
                var ctr = new WidgetStackContainer();
                ctr.Name = "R1C0";
                ctr.Background = Colors.LightPink;
                grid.SetRowCol(ctr, 1, 0, 1, 2);
                grid.Children.Add(ctr);
            }
            {
                var ctr = new WidgetStackContainer();
                ctr.Name = "R2C1";
                ctr.Background = Colors.MediumSlateBlue;
                grid.SetRowCol(ctr, 2, 1, 1, 2);
                grid.Children.Add(ctr);

                ctr.Children.Add(btn_next);
            }

            this.Content = grid;
        }

        void btn_prev_Click(object sender, EventArgs e)
        {
            NavigationService.Instance.GoBack();
        }

        void btn_next_Click(object sender, EventArgs e)
        {
            NavigationService.Instance.Navigate(new DemoPage3());
        }
    }

That leads the following snapshot:

My Snapshot5

NOTE: by live the display shows the colors correctly. However, the picture taken renders a bad result.

Widgets, widgets, widgets…

The Eve board is very well designed, because it’s plenty of useful widgets. I don’t believe you’d need something different from the provided.
At the moment of writing, the Netduino library supports:

  • (normal) Button
  • ToggleButton
  • TextBlock
  • Slider
  • Dial

and, as for the layout control:

  • StackPanel
  • Grid

As long the spare time helps me, I will try to add some other useful component as the TextBox and the Image.

Yet some screens generated by the Netduino and the FT800 Eve board.
WP_000595

My Snapshot4

My Snapshot3

My Snapshot7

Source code

I will release a beta release soon.

 
2 Comments

Posted by on February 16, 2014 in .Net, Electronics, Software

 

Tags: , , , , , , , , , , ,

Microsoft TechDays 2013 Paris: une grand merci!

The greatest Microsoft event of Europe has just been closed in Paris, France.
I am soooo honored to have been mentioned in the “Geek in da House” session of Laurent Ellerbach.

Image00001

He presented two very interesting projects, both of them involving Netduino and a little hardware around.
In the first part of his session, Laurent presents his remotely controlled gardening sprinkler system. Afterward, his Netduino is used in a totally different way: as transmitter for IR commands against a Lego train. My help was just on the latter project.
Here is the link of the video (French speaking).
Have fun!

 
Leave a comment

Posted by on February 17, 2013 in .Net, Electronics, Software

 

Tags: , , , , ,

A playable Invaders-like game with a Netduino Plus 2

Finally here is my last article of the series about the GDI library for Netduino and how to use it.
The post guides you on how to create your own game, such an Invaders-like playable game.

WP_000337

WP_000321
Enjoy!

 
Leave a comment

Posted by on February 17, 2013 in .Net, Electronics, Software

 

Tags: , , , , , , ,

The GDI library for Netduino targets a LCD module

This time the article will show you how to use the GDI library for Netduino for driving a very common LCD character module.

Enjoy!

 
Leave a comment

Posted by on February 16, 2013 in .Net, Electronics, Software

 

Tags: , , , , , , ,

Animation with the GDI library for Netduino

This is my third article about the GDI library for Netduino.
This time the discussion is on how to create a simple animation for the Sure Electronics led-matrix.
Enjoy!

 
Leave a comment

Posted by on February 14, 2013 in .Net, Electronics, Software

 

Tags: , , , , , , ,

A simple yet versatile GDI library for Netduino

Okay, here is another article of mine regarding the led-matrix. It is a step-by-step tutorial on how to create static drawings with the GDI library for Netduino.

WP_000293
Have fun!

 
Leave a comment

Posted by on February 10, 2013 in Electronics

 

Tags: , , , , , ,

Sure Electronics Led-matrix driver for Netduino

Finally I done it!
Here is a link to my article explaining how to drive a Sure Electronics led-matrix module with a Netduino (Plus) 2.


Enjoy!

 
Leave a comment

Posted by on February 10, 2013 in Electronics

 

Tags: , , , , ,

Modbus libraries version 2 beta are out!

Today I published the version 2 (beta) of the Modbus libraries suite.
The most noticeable news is about the ordinary desktop .Net 4.5 support. This comes along a stunning Windows Store-like demo app for bidirectional testing with any Modbus-enabled Netduino.

demo0

demo1

demo2

demo3

This demo has been styled upon the brand-new Windows 8 “Modern-UI” rules, so that the incoming Windows RT libraries will feature a similar demo running on a tablet instead.

I also added the Windows Phone 8 support, but it looks exactly as the previous Windows Phone 7.5 release. I tested it only with the emulator not having any WP8-enabled phone.

Stay tuned!

 
1 Comment

Posted by on January 17, 2013 in .Net, Electronics, Software

 

Tags: , , , , , ,

How to get our Netduino running faster

Before going on on my graphic library for led matrix, I think it’s time to optimize a bit the code in order to get the Netduino running faster.
My job is programming application using .Net for desktop, but a PC is very rich of resources such as RAM and processor speed. Instead, the Micro Framework offers a very small environment where every byte more might have an impact on the final result.
running_cheetah_320x240
Here is a brief bunch of tests for showing a comparison on different approaches against a same task. Sometime you don’t care about the best way to write the code, but the interesting thing is actually knowing how the things are working. You will be surprised, as I was.

The test bench.

The base program for the tests is very simple: it is an endless loop where the code under test runs interleaved by a short pause of 100ms. The comparison is mostly against different yet commonly-used types, such as Int32, Single, Double and Byte.
The timings are taken by using a scope, then watching at two output ports when they change their state.
Except for the very first, each test cycles 50 times over a 20-operations set: that for minimize the overhead due to the “for-loop”. By the way, the first test is targeted just for get the “for-loop” heaviness.
It follows the test program template:

namespace PerformanceTest
{
    public class Program
    {
        private const int Count = 50;

        private static OutputPort QTest = new OutputPort(Pins.GPIO_PIN_D0, false);
        private static OutputPort QPulse = new OutputPort(Pins.GPIO_PIN_D1, false);


        public static void Main()
        {
            byte b;
            byte bx = 50;
            byte by = 16;

            int i;
            int ix = 50;
            int iy = 16;

            float f;
            float fx = 50.0f;
            float fy = 16.0f;

            double d;
            double dx = 50.0;
            double dy = 16.0;

            while (true)
            {
                //start of the test
                QTest.Write(true);


                // ... operations to test ...


                //end of the test
                QTest.Write(false);
                Thread.Sleep(100);
            }
        }


        private static void Pulse()
        {
            QPulse.Write(true);
            QPulse.Write(false);
        }

    }
}

The basic for-loop.

Since every test will use the “for-loop”, we should measure how much overhead that introduces.
Here is the snippet…

                for (int n = 0; n < 1000; n++)
                {
                    //do nothing
                }

…and here is the timing:
UNIT0000

Roughly speaking, we could say that every for-loop cycle takes about 7 microseconds.

How does look the IL-opcodes generated by the compiler (restricted to the only for-loop)?
Well, it is pretty interesting digging a bit behind (or under?) the scenes. I will take advantage by the awesome ILSpy, which is a free, open-source decompiler, disassembler and much more provided by the SharpDevelop teams.

		IL_0042: ldc.i4.0
		IL_0043: stloc.s n
		IL_0045: br.s IL_004f
		// loop start (head: IL_004f)
			IL_0047: nop
			IL_0048: nop
			IL_0049: ldloc.s n
			IL_004b: ldc.i4.1
			IL_004c: add
			IL_004d: stloc.s n

			IL_004f: ldloc.s n
			IL_0051: ldc.i4 1000
			IL_0056: clt
			IL_0058: stloc.s CS$4$0000
			IL_005a: ldloc.s CS$4$0000
			IL_005c: brtrue.s IL_0047
		// end loop

Notice how the final branch-on-true jumps back to the first opcode, which implies a couple of “nop”s: why?
Anyway, we are not going to optimize the for-loop yet.

Addition.

The addition will be performed over three common types: Int32, Single and Double.
Here is the snippet…

                for (int n = 0; n < Count; n++)
                {
                    i = ix + iy; //repeated 20 times
                }

                Pulse();

                for (int n = 0; n < Count; n++)
                {
                    f = fx + fy; //repeated 20 times
                }

                Pulse();

                for (int n = 0; n < Count; n++)
                {
                    d = dx + dy; //repeated 20 times
                }

…and here is the timing:
UNIT0001

Again, an “average” addition takes about 2 microseconds.

Many users are blaming the poor speed of a board like Netduino, because its core can run at over 200Mips. Two microseconds for an addition (integer or floating-point) seems a waste of performance, but…please, bear in mind that a so small yet inexpensive board performs similar about the same as an old 1984 IBM PC-AT machine (estimated price US$5000).

The interesting thing is that there’s almost no difference between using Int32 or Single, whose are both 32-bit based. Surprisingly, even choosing Double as type, the calculation takes insignificantly longer than the other cases. However, a Double takes 8 bytes.
Below there are the parts of IL whose depict the operations:

                        // ...

			IL_004e: ldloc.s ix
			IL_0050: ldloc.s iy
			IL_0052: add
			IL_0053: stloc.3
                        
                        // ...

			IL_00eb: ldloc.s fx
			IL_00ed: ldloc.s fy
			IL_00ef: add
			IL_00f0: stloc.s f
                        
                        // ...

			IL_019c: ldloc.s dx
			IL_019e: ldloc.s dy
			IL_01a0: add
			IL_01a1: stloc.s d
                        
                        // ...

Multiplication.

Here is the snippet…

                for (int n = 0; n < Count; n++)
                {
                    i = ix * iy; //repeated 20 times
                }

                Pulse();

                for (int n = 0; n < Count; n++)
                {
                    i = ix << 4; //repeated 20 times
                }

                Pulse();

                for (int n = 0; n < Count; n++)
                {
                    f = fx * fy; //repeated 20 times
                }

                Pulse();

                for (int n = 0; n < Count; n++)
                {
                    d = dx * dy; //repeated 20 times
                }

…and here is the timing:
UNIT0002

As for the addition, the multiplication takes almost the same time to perform and it seems there’s no significant loss of performance over different data types.
There is an extra-special case, which calculates the multiplication leveraging the left-shift operator. It’s a very particular case, but it’s noticeable the better speed than an ordinary multiplication. Is it worthwhile choosing a shift over a real multiplication? I don’t believe…
Below there are the parts of IL whose depict the operations:

                        // ...

			IL_004e: ldloc.s ix
			IL_0050: ldloc.s iy
			IL_0052: mul
			IL_0053: stloc.3
                        
                        // ...

			IL_00e8: ldloc.s ix
			IL_00ea: ldc.i4.4
			IL_00eb: shl
			IL_00ec: stloc.3
                        
                        // ...

			IL_016e: ldloc.s fx
			IL_0170: ldloc.s fy
			IL_0172: mul
			IL_0173: stloc.s f
                        
                        // ...

			IL_021f: ldloc.s dx
			IL_0221: ldloc.s dy
			IL_0223: mul
			IL_0224: stloc.s d
                        
                        // ...

Logical AND.

Here is the snippet…

                for (int n = 0; n < Count; n++)
                {
                    i = ix & iy; //repeated 20 times
                }

                Pulse();

                for (int n = 0; n < Count; n++)
                {
                    b = (byte)(bx & by); //repeated 20 times
                }

…and here is the timing:
UNIT0003

It is clear that a logical operation like the AND takes almost the same as an ordinary addition between Int32-s. Instead, the interesting thing is seeing how different is working with Int32 and Byte.
Any .Net Framework operates at least on 32-bits operands (whereas possible it uses 64-bits). Thus, when you constrain your variables to a tiny byte, most operations will cast the values to Int32-s. That takes much more time to do and demonstrates why in the .Net world the speculation habits of small CPUs are wrong.
Below there are the parts of IL whose depict the operations:

                        // ...

			IL_004e: ldloc.s ix
			IL_0050: ldloc.s iy
			IL_0052: and
			IL_0053: stloc.3
                        
                        // ...

			IL_00e8: ldloc.1
			IL_00e9: ldloc.2
			IL_00ea: and
			IL_00eb: conv.u1
			IL_00ec: stloc.0
                        
                        // ...

Min/Max calculation.

Here is the snippet…

                for (int n = 0; n < Count; n++)
                {
                    i = System.Math.Min(ix, iy);
                    i = System.Math.Max(ix, iy);
                    // ... repeated 10 times
                }

                Pulse();

                for (int n = 0; n < Count; n++)
                {
                    i = ix < iy ? ix : iy;
                    i = ix > iy ? ix : iy;
                    // ... repeated 10 times
                }

                Pulse();

                for (int n = 0; n < Count; n++)
                {
                    i = ix; if (ix < iy) i = iy;
                    i = ix; if (ix > iy) i = iy;
                    // ... repeated 10 times
                }

…and here is the timing:
UNIT0005

Please, bear in mind that the time is 5x than the above charts.

Using a library function is preferable: we should avoid “reinventing the wheel” and most of the times a library function embeds native code and yields faster results. However, when that function is particularly simple, it could be better choosing another approach, such as in this example.
The timings clear shows that calling the framework’s Min/Max function takes about three-times than using a trivial ternary-if. Even using a third attempt for calculating the min/max yields no better results other than the most trivial way.
Let’s have a peek at the IL assembly:

                        // ...

			IL_004e: ldloc.s ix
			IL_0050: ldloc.s iy
			IL_0052: call int32 [mscorlib]System.Math::Min(int32, int32)
			IL_0057: stloc.3
                        
                        // ...

			IL_013b: ldloc.s ix
			IL_013d: ldloc.s iy
			IL_013f: blt.s IL_0145

			IL_0141: ldloc.s iy
			IL_0143: br.s IL_0147

			IL_0145: ldloc.s ix

			IL_0147: stloc.3
                        
                        // ...

			IL_0264: ldloc.s ix
			IL_0266: stloc.3
			IL_0267: ldloc.s ix
			IL_0269: ldloc.s iy
			IL_026b: clt
			IL_026d: ldc.i4.0
			IL_026e: ceq
			IL_0270: stloc.s CS$4$0000
			IL_0272: ldloc.s CS$4$0000
			IL_0274: brtrue.s IL_0279

			IL_0276: ldloc.s iy
			IL_0278: stloc.3
                        
                        // ...

Sample expression.

Here is the snippet…

                for (int n = 0; n < Count; n++)
                {
                    d = ix * (fx + dx) * (fy + dy); //repeated 20 times
                }

                Pulse();

                for (int n = 0; n < Count; n++)
                {
                    d = ix; 
                    d *= fx + dx; 
                    d *= (fy + dy);
                    // ... repeated 20 times
                }

…and here is the timing:
UNIT0004

The timings are showing that an inline-expression performs better than a compound operator. That’s normal, because the compiler actually does what the user wrote: store each intermediate operation in the variable. That forces the compiler to avoid optimizations such as in the inline syntax.
The IL opcodes demonstrate the longer task in the second case:

                        // ...

			IL_004e: ldloc.s ix
			IL_0050: conv.r8
			IL_0051: ldloc.s fx
			IL_0053: conv.r8
			IL_0054: ldloc.s dx
			IL_0056: add
			IL_0057: mul
			IL_0058: ldloc.s fy
			IL_005a: conv.r8
			IL_005b: ldloc.s dy
			IL_005d: add
			IL_005e: mul
			IL_005f: stloc.s d
                        
                        // ...

			IL_01ef: ldloc.s ix
			IL_01f1: conv.r8
			IL_01f2: stloc.s d
			IL_01f4: ldloc.s d
			IL_01f6: ldloc.s fx
			IL_01f8: conv.r8
			IL_01f9: ldloc.s dx
			IL_01fb: add
			IL_01fc: mul
			IL_01fd: stloc.s d
			IL_01ff: ldloc.s d
			IL_0201: ldloc.s fy
			IL_0203: conv.r8
			IL_0204: ldloc.s dy
			IL_0206: add
			IL_0207: mul
			IL_0208: stloc.s d
                        
                        // ...

Conclusion.

As a professional programmer, I ma obsessed by well-written source code, patterns, good-practices and so away. However, I also believe it’s useful to know when and how put your finger on a program to get the most from it.
That is also a good programming practice, IMHO.

 
13 Comments

Posted by on January 5, 2013 in .Net, Software

 

Tags: , , , ,

 
Follow

Get every new post delivered to your Inbox.

Join 75 other followers