A little old thread, it's 2022 now…
I had a bunch of short
s laying around (sorry, no int
s ;-) ) and thought it would be cool to have them as a byte array instead. After reading about all the different ways to approach this, I was very confused and just started benchmarking my favourite ones.
(The code should be easy to apply to any base type.)
It uses BenchmarkDotNet
to do the actual testing and statistical analysis.
using System;
using System.Linq;
using System.Runtime.InteropServices;
using BenchmarkDotNet.Attributes;
using BenchmarkDotNet.Running;
namespace ArrayCastingBenchmark;
public class Benchy {
private const int number_of_shorts = 100000;
private readonly short[] shorts;
public Benchy() {
Random r = new(43);
shorts = new short[number_of_shorts];
for (int i = 0; i < number_of_shorts; i++)
shorts[i] = (short) r.Next(short.MaxValue);
}
[Benchmark]
public ReadOnlySpan<byte> SPANSTYLE() {
ReadOnlySpan<short> shortSpan = new ReadOnlySpan<short>(shorts);
return MemoryMarshal.Cast<short, byte>(shortSpan);
}
[Benchmark]
public byte[] BLOCKCOPY() {
byte[] bytes = new byte[shorts.Length * sizeof(short)];
Buffer.BlockCopy(shorts, 0, bytes, 0, bytes.Length);
return bytes;
}
[Benchmark]
public byte[] LINQY() {
return shorts.Select(i => (byte) i).ToArray();
}
[Benchmark]
public byte[] BITCONVERTER() {
byte[] bytes = shorts.SelectMany(BitConverter.GetBytes).ToArray();
return bytes;
}
//[Benchmark]
//public void BINARYWRITER() {
// var fhandle = File.OpenHandle("_shorts_binarywriter.bin", FileMode.Create, FileAccess.Write);
// var binaryWriter = new BinaryWriter(new FileStream(fhandle, FileAccess.Write));
// foreach (var shorty in shorts)
// binaryWriter.Write(shorty);
// binaryWriter.Flush();
// binaryWriter.Close();
// fhandle.Close();
//}
}
internal class Program {
static void Main(string[] args) {
var summary = BenchmarkRunner.Run<Benchy>();
}
}
I left the last one in, because if you just add a File.WriteAllBytes
to the end of all methods and make them actually produce some output, suddenly BLOCKCOPY
get's ever so slightly faster than SPANSTYLE
on my machine. If anyone else experiences this or has an idea how this can happen, please tell me.
EDIT:
Sorry, forgot to include the actual results (mind you: on my machine) as it runs for quite a while with the standard settings and all the warm-up.
| Method | Mean | Error | StdDev |
|------------- |------------------:|----------------:|----------------:|
| SPANSTYLE | 0.4592 ns | 0.0333 ns | 0.0666 ns |
| BLOCKCOPY | 15,384.8031 ns | 304.6014 ns | 775.3079 ns |
| LINQY | 175,187.7816 ns | 1,119.2713 ns | 1,046.9671 ns |
| BITCONVERTER | 9,053,750.0355 ns | 330,414.7870 ns | 910,058.2814 ns |
byte array
and "bigger thanshort
" mismatch. – Henk Holterman