I\'m interested in how efficient low-level algorithms can be in .net. I would like to enable us to choose to write more of our code in C# rather than C++ in the future, but
First of all, I would like to thank everyone who spoken out in this post, from original OP to the guys who provided extremely detailed and insightful explanations. I really, really enjoyed reading the existing answers. Since there is already plentiful of theory of how and why the loops work in the way they do, I would like to offer some empirical (by some definition authoritative) measurements:
Conclusions:
.Length property.unsafe fixed is not faster than normal For loop.Benchmarking code:
using System;
using System.Diagnostics;
using System.Runtime;
namespace demo
{
class MainClass
{
static bool ByForArrayLength (byte[] data)
{
for (int i = 0; i < data.Length; i++)
if (data [i] != 0)
return false;
return true;
}
static bool ByForLocalLength (byte[] data)
{
int len = data.Length;
for (int i = 0; i < len; i++)
if (data [i] != 0)
return false;
return true;
}
static unsafe bool ByForUnsafe (byte[] data)
{
fixed (byte* datap = data)
{
int len = data.Length;
for (int i = 0; i < len; i++)
if (datap [i] != 0)
return false;
return true;
}
}
static bool ByForeach (byte[] data)
{
foreach (byte b in data)
if (b != 0)
return false;
return true;
}
static void Measure (Action work, string description)
{
GCSettings.LatencyMode = GCLatencyMode.LowLatency;
var watch = Stopwatch.StartNew ();
work.Invoke ();
Console.WriteLine ("{0,-40}: {1} ms", description, watch.Elapsed.TotalMilliseconds);
}
public static void Main (string[] args)
{
byte[] data = new byte[256 * 1024 * 1024];
Measure (() => ByForArrayLength (data), "For with .Length property");
Measure (() => ByForLocalLength (data), "For with local variable");
Measure (() => ByForUnsafe (data), "For with local variable and GC-pinning");
Measure (() => ByForeach (data), "Foreach loop");
}
}
}
Results: (uses Mono runtime)
$ mcs Program.cs -optimize -unsafe
For with .Length property : 440,9208 ms
For with local variable : 333,2252 ms
For with local variable and GC-pinning : 330,2205 ms
Foreach loop : 280,5205 ms