Even if all of us are really happy while writing fast and easy, some of us are also concerned by performance issues of our application. Of course there’s RLP as the final solution but this involves heavier development. Instead I think this would be very interesting to have a tutorial and a dedicated forum area for this purpose.
For the programmer, there are really only two things worth noting. First, that the JIT is very intelligent. Don’t try to outthink the compiler. Code the way you would normally. For example, suppose you have the following code:[/quote]
...
for(int i = 0; i < myArray.length; i++){
...
}
...
Instead of
...
int l = myArray.length;
for(int i = 0; i < l; i++){
...
}
...
[quote]Some programmers believe that they can get a speed boost by moving the length calculation out and saving it to a temp, as in the example on the right.
The truth is, optimizations like this haven’t been helpful for nearly 10 years: modern compilers are more than capable of performing this optimization for you. In fact, sometimes things like this can actually hurt performance. In the example above, a compiler would probably check to see that the length of myArray is constant, and insert a constant in the comparison of the for loop. But the code on the right might trick the compiler into thinking that this value must be stored in a register, since l is live throughout the loop. The bottom line is: write the code that’s the most readable and that makes the most sense. It’s not going to help to try to outthink the compiler, and sometimes it can hurt.[/quote]
However I observed the opposite in my benchmark and would like to discuss about that with people that are also concerned by these kind of problem.
@ GHI team could it be possible to have a dedicated area to expose guidelines or good practices and a forum to discuss about that?
I notice that topic is for the .Net framework, not the .Net Micro Framework. I think it’s important to say that, because I feel that while you have horsepower to burn (.Net) this is a non-issue, but as you note there’s gains to be had when you’re so close to the processor. There are probably enough JIT differences too to make it more relevant.
If we wanted a separate “sub forum” then I’d call it something like “Performance tips when you need it most”. If you are just “here” to talk about why netmf isn’t real time and why you can’t toggle a pin at 36mhz, then that’s a whole different kettle of fish
You got it, the fact is that the programming scheme used for other devices or other environments are in some cases not efficient for .netmf. In most of languages and compiler, constant propagation works well as claimed by the document from the big .net, whereas the same assumption is not true for .netmf. This is why I think that this kind of performance subforum would be relevant.
I know that .netmf is not realtime, even even if it was, the problem is not to have due date, semaphore, locking mechanisms and so on such like LinuxRT or windriver OS but the fact that .netmf devices when badly programmed can achieve very poor performance and I think that we (I) need to learn to program better on .netmf devices. To me embedded systems does not mean necessarly slow…
So, @ GHI team it 's up to you to open a subforum for that.
using System;
using Microsoft.SPOT;
using GHIElectronics.NETMF.Hardware;
namespace EMX_Application1
{
public class Program
{
static readonly string hex = "0123456789ABCDEF";
public static void Main()
{
string s = "sdkjqsdhslqkdjfgsqdklfgkgfgcfozepokzefùnwlukfyhcqlernhyuhfskdjfgsdk";
Debug.Print(Resources.GetString(Resources.StringResources.String1));
DateTime start = DateTime.Now;
for(int i = 0;i < 1000;i++)
{
MEA_GetChecksum(s);
}
DateTime end = DateTime.Now;
Debug.Print("Compute NMEA Checksum performs in" + (end - start).Ticks / 10 + " micro seconds");
start = DateTime.Now;
for(int i = 0;i < 1000;i++)
{
MEA_GetChecksum2(s);
}
end = DateTime.Now;
Debug.Print("Compute NMEA Checksum performs in" + (end - start).Ticks / 10 + " micro seconds");
}
//-----------------------------------------------------------------------//
public static string MEA_GetChecksum(string trame)
{
int Checksum = trame[0];
int size = trame.Length;
for(int i = 1;i < size;i++)
{
Checksum ^= trame[i];
}
byte b = (byte)(Checksum & 0xFF);
return new string(new char[] { hex[(b & 0xF0) >> 4],hex[b & 0x0F] });
}
public static string MEA_GetChecksum2(string trame)
{
int Checksum = trame[0];
for(int i = 1;i < trame.Length;i++)
{
Checksum ^= trame[i];
}
byte b = (byte)(Checksum & 0xFF);
return new string(new char[] { hex[(b & 0xF0) >> 4],hex[b & 0x0F] });
}
}
}
This returns 15275046µs for the first function vs 23085392µs for the second one; this makes a huge gap and therefore a first rule for the good practices would be to not considering that constant propagation and ssa will optimize loop parameter. Therefore we need to put outside of the loop, the length computation.
Hi Gus and thanks for your interest. You’re right a wiki is a good option to write the rules for “high performance” computing on .netmf, the idea of creating a sub forum was to have a kind of separation of concern, the forum start to be really big now and sometimes it is difficult to follow all the activity. It sounds to me that creating a category or a subcategory performance is a solution to not pollute the rest of the forum, and to be not polluted by other discusion but may be I am wrong.
Since you have Debug.Print statements, I suppose the first. In debug don’t hope for any optimisation. If you step through the code you will see that each loop it will call the getter of string.Length. In release, the compiler could be clever and it could see that the string is not altered so length will never change.
However I doubt that this optimisation will occure as there might be an other thread modifying the string in the meanwhile (putting aside thread-safety). If you ask me, the getter will always be called, regardless of the optimalisation level.
Wouter maybe you have the point about the fact that there’s no optimization and constant propagation but then why this is available and claimed by MS on the big.net (where multithreading has a bigger impact in terms of runtime than on our devices).
I see that that MSDN article is over a decade old now… Wonder if they would change anything now or if it’s all still valid…
Anyway, I don’t like this:
[quote=“leforban”]…
...
for(int i = 0; i < myArray.length; i++){
...
}
...
Instead of
...
int l = myArray.length;
for(int i = 0; i < l; i++){
...
}
...
[quote]Some programmers believe that they can get a speed boost by moving the length calculation out and saving it to a temp, as in the example on the right.
The truth is, optimizations like this haven’t been helpful for nearly 10 years: modern compilers are more than capable of performing this optimization for you. In fact, sometimes things like this can actually hurt performance. In the example above, a compiler would probably check to see that the length of myArray is constant, and insert a constant in the comparison of the for loop. …[/quote][/quote]
The word “constant” here makes me cringe a little because “constant” (or, rather, “const”) means something specific in C# and what it means is not what they’re talking about.
They also miss the whole property vs field thing. They imply that it’s a straight C# [] array, which would make the example pretty valid, but it could well be that .length is a field with a bunch of code to walk a list or even make external calls to determine the length of the collection. In those cases, the example would be totally wrong and it’d be far more efficient to copy the current length before the loop.
I guess my point is that blanket rules like this can be a little dangerous without context.
Back to the point of this thread, I wouldn’t mind seeing a forum thread or 3 about performance-related topics with the results/conclusions getting to the wiki. Maybe even a generic codeshare library that does various tests and reports timings so people can see how their particular hardware behaves with different code scenarios. One thing that I’d like to see is some tests around call overhead of properties vs simple fields and of methods in general.
The fact is here, programming the first will result in poor performance of the algorithm while the second is really better. Usually on modern compilers, such kind of situation is detected by the compiler and programmer do not have to take care of such thing. But the .netmf compiler is not a real compiler, it creates IL that runs on a VM and this can be the reason. Anyway, for people like me that need to have low latency devices or high throughput computation, we need guidelines when writing code and as far as I know there’s no centralized documentation for that purpose. the only way to evaluate efficiency of our code is to spent a hard time to check several solution.
Remember, in NETMF, there is no JIT, so anywhere you see that the JIT will perform optimizations, those optimizations are NOT happening on NETMF. In NETMF, the MSIL is interpreted at runtime.
If .length is a property or a simple field. If it’s not, it’s not better.
A truely horrible example of what I’m saying:
class RandomEvens
{
public int length
{
get
{
Random r = new Random();
int[] data = new int[r.Next(100)];
for (int i = 0; i < data.Length; i++)
data[i] = r.Next(100);
int evens = 0;
foreach (int i in data)
{
if ((i & 0x01) == 0)
evens++;
}
return evens;
}
}
}
I think his point is that if .length is a property, it might be doing a lot of work instead of simply returning a value. If .length is a field, then it’s not possible for it to be doing work.
My objection was to the blanket statement saying it’s always more efficient to do this without also saying that it’s only really true for fields:
for(int i = 0; i < myArray.length; i++){
My horrible example code was of a property (not a field) called .length where it would have been far, far more efficient to call .length once, before the loop.
Ok I got it. My assumption was to say that calling something.length is bad in the loop parameter, as I explained, it concerns only the length computation of an array or a collection, not a field of a struct. Am I right now?
Edit: after reading more this post, I believe that it is not easy to edict clearly the rules and this is why it is particularly important to debate and exchange before submitting any rule.
If it’s just a field, go ahead and use it as the loop condition - like the MSDN article said, the compiler may be able to do clever things for you. If it’s not a field or if you don’t know what it’s doing underneath the covers, it may be better to just call it once, before the loop.
My objection was really to the blanket rule that one way is always better than the other… Rules like that usually have exceptions, which they probably should have noted.
No, I am maybe not enough clear, I am just observing the opposite of the MSDN link. So optimization is not performed by the compiler, that is why I was believing that the rule that says: “you won’t use the length computation as a loop parameter” was true.
But you seem to say that this is not true due to the fact that .length can be a property or a field, whereas I talk about a length computation not a field. With this in mind are we OK?
I goofed around with this a bit last night and my results were the same as yours - it’s faster to get the length once, before the loop. Various combinations of doing the tests in different order and calling GC vs not calling it and everything else I could think of did not change the result. This was a Spider on 4.1 with a int[], BTW.
Don’t know why that MSDN article says otherwise but now I doubly-object to that part of it!