Here are the results, and the code follows below (run on Windows 7 64bit dual core).
Array length: 1048576
Iterations: 1000
Enumerable: 00:00:12.3817249
Parallel Enumerable: 00:00:17.6506353
For loop: 00:00:01.7095341
Parallel for loop: 00:00:06.9824434
Unsafe: 00:00:00.7028914
static void Fill1(byte value)
{
byte[] a = Enumerable.Repeat<byte>(value, _arrLength).ToArray();
}
static void Fill2(byte value)
{
byte[] a = ParallelEnumerable.Repeat<byte>(value, _arrLength).ToArray();
}
static void Fill3(byte value)
{
byte[] a = new byte[_arrLength];
for (int i = 0; i < _arrLength; i++)
{
a[i] = value;
}
}
static void Fill4(byte value)
{
byte[] a = new byte[_arrLength];
Parallel.For(0, _arrLength, i =>
{
a[i] = value;
});
}
static unsafe void Fill5(byte value)
{
Int64 fillValue = BitConverter.ToInt64(new byte[] { value, value, value, value, value, value, value, value }, 0);
byte[] a = new byte[_arrLength];
Int64* src = (Int64*)&fillValue;
fixed (byte* ptr = &a[0])
{
Int64* dest = (Int64*)ptr;
int length = _arrLength;
while (length >= 8)
{
*dest = fillValue;
dest++;
length -= 8;
}
byte* bDest = (byte*)dest;
for (byte i = 0; i < length; i++)
{
*bDest = value;
bDest++;
}
}
}



can C# do duff's device? I wonder how it would preform? (:
ReplyDeletethanks for profiling this stuff, it makes the choice pretty clear... I'm going with the for loop because i don't think i can use so called "unsafe" code in my situation.
Thanks man!
Glad you found it helpful :)
ReplyDeleteFound an implementation of Duff's Device at http://www.giannistsakiris.com/index.php/2007/07/17/duffs-device/ which I modified to set just one value. When running many tests it 9/10 times performs marginally faster than the for loop and then 1/10 slower or the same.
I would go with the for loop as well for most cases.
public static void Fill6(byte value)
{
byte[] toBuffer = new byte[_arrLength];
int count = _arrLength;
int i = 0;
if (count%8 == 7) goto case_7;
if (count%8 == 6) goto case_6;
if (count%8 == 5) goto case_5;
if (count%8 == 4) goto case_4;
if (count%8 == 3) goto case_3;
if (count%8 == 2) goto case_2;
if (count%8 == 1) goto case_1;
case_0:
toBuffer[i++] = value;
case_7:
toBuffer[i++] = value;
case_6:
toBuffer[i++] = value;
case_5:
toBuffer[i++] = value;
case_4:
toBuffer[i++] = value;
case_3:
toBuffer[i++] = value;
case_2:
toBuffer[i++] = value;
case_1:
toBuffer[i++] = value;
if ((count -= 8) > 0) goto case_0;
}