Categories
Main

Exploring the Netduino #1: Takin’ her for a Test Drive

From the last post on Exploring the Netduino, we learned that the Netduino is a lot like the Arduino Uno in physical and electrical aspects, but the Netduino has a few advantages in its court: ~3 times the processing power, 32-bit ARM7, and nearly 30x the RAM. But it was also noted that the Netduino runs a slimmed down version of the .NET Micro Framework (NETMF) which naturally will require more overhead than the native binaries that are compiled down tightly for the Arduino Uno’s ATmega328 8-bit AVR processor.

If you have a Netduino (or are thinking of getting one) and have not yet tried out (or looked at) the Netduino “Getting Starting” guide, I recommend reading it. It walks the reader through setting up their development environment and then writing a simple “Hello, World” type program which gets the little blue light on the board to blink. Unfortunately, this introduction is quite limited and might leave you saying “Well, blinking a blue light was fun, but what next?” Glad you asked!

Depending on the complexity of what you are trying to create, you might have a need for various types of Data Structures. Microsoft’s NETMF ver. 4.1 affords the programmer a lot of what he or she might expect in the regular .NET 4.0 framework, but it should be warned that a lot of normal .NET is missing, too. Maybe we should start with the bad news first.

What’s MISSING from NETMF:

  • Generics
  • SqlClient
  • StringBuilder
  • String.Format

The first one is a tragedy in some ways as not having Generics is like being pushed back to the stone age of .NET 1.x — Yup, that’s right. Your favorite data structures like List<T> and Dictionary<K,V> are both gone. But let’s face it: Any programmer worth their salt should be able to work with this.

The last 3 are niceties that have been removed for the sake of not making the NETMF any bigger than it needs to be. StringBuilder also uses a ton of memory, which is really at a premium with these microcontrollers. No need for it here. The good news is that LINQ, Lambda Expressions, and Extension Methods all work — the catch? Due to the lack of Generics you will need to provide your own “casts” in the right places. (And catch exceptions, but we are all good little programmers that properly catch our exceptions, right?)

The data structures that *are* available?

  • Array
  • ArrayList
  • HashTable
  • Stack
  • Queue

All good things to have, but Remember: No Generics. So you cannot declare data types, but you can still stuff whatever you want into these data structures. (Well, except for the plain-old Array.) Just be careful when mixing types to type-check and cast when necessary. And of course, we still have Classes and Structs and Interfaces. Wanna declare your variable using “var” instead of the specific type? Go for it. It’s there, too.

Let’s take this baby for a test drive!

Since the Netduino is a microcontroller, it has its limitations. Perhaps the biggest one is the limited RAM: Only 60KB, according to the specs. In combination with NETMF, this could be tricky. One of the first things that I tried was creating an ArrayList and repeatedly “Add”-ing additional values to the ArrayList. Specifically, 32-bit integers.

[cc lang="csharp"]
    public class Program
    {
        public static void Main()
        {
            Debug.Print("-----[ ArrayList Int allocation Test ]-----");
            var testArrayList = new ArrayList();
            for (int i = 0; i < 15000; i++)
            {
                try
                { testArrayList.Add(i); }
                catch
                {
                    Debug.Print("Count = " + i.ToString());
                    break;
                }
            }
        }
    }[/cc]

Upon running this code, the Debug (Output) window spat out the line:  Count = 711

Interesting. The ArrayList maxed out that 60KB of memory with only 710 Integers (32-bit). That’s a lot of overhead just to hold 2.84 KB worth of Integers. So what about a plain-old Array of Ints? How much that would hold?

From my tests: just shy of 13,200 Integers. According to my math, this is ~ 52.8KB — That’s much more efficient and about what I would expect from an Array of Ints.

Improving memory efficiency of ArrayList

After chatting with some of the folks over at the Netduino forums, we determined that additional space could be had due to the Garbage Collector “holding back” (so to speak.) To correct this, the attempted solution was to add one line in the allocation loop above.

Debug.GC(true);

By adding this line, each pass of the loop forces garbage collection to take place. Certainly this slows down the operation of the Netduino, but it did allow the ArrayList to allocate 1065 Integers (instead of just 710.) A full 50% improvement! But still depressingly low.

So the lesson for now is: Be judicious with the use of ArrayList. It’s not very memory efficient.

Next time: (Indirectly) Driving an LED

6 replies on “Exploring the Netduino #1: Takin’ her for a Test Drive”

Hi,

why is there an exception thrown?
Shouldn’t the CLR notice the full memory and start the GC automatically?
Why I have to do it manually?

Based in the behaviour of the normal .net framework the ArrayList behaviour is going to be down to a combination of:

Boxing to put in the object typed list (I assume 4 bytes in the list itself and 8+4 on the heap for each entry.

The array list will expand by doubling capacity on the backing array.
This will mean you temporarily need 3 times as much memory as are required to get the next element in as it cannot resize the current one.
The doubling also often makes the final terminal allocation quite slot bigger than is strictly required.

You can avoid the latter by pre sizing, but not the former.

The final problem is likely to be true but I couldn’t swear to it because I don’t know how the heap works in the MF.
Some level of fragmentation will cause you an issue as time goes along due to the afore mentioned doubling coupled with the bitty boxed ints.

Leave a Reply

Your email address will not be published. Required fields are marked *