Skip to content

Instantly share code, notes, and snippets.

@ufcpp
Created November 8, 2018 12:40
Show Gist options
  • Star 0 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save ufcpp/efb726420adc6f8183a5c7a92ff17a61 to your computer and use it in GitHub Desktop.
Save ufcpp/efb726420adc6f8183a5c7a92ff17a61 to your computer and use it in GitHub Desktop.
要素の型がわかっている場合の配列ダウンキャスト
using BenchmarkDotNet.Attributes;
using BenchmarkDotNet.Running;
using System.Runtime.CompilerServices;
public class ArrayDowncastBenchmark
{
string[] _stringData = new string[] { "a", "ab", "abc", "abcd", "abcde", "abcdef", "abcdefg" };
object[] _objectData = new string[] { "a", "ab", "abc", "abcd", "abcde", "abcdef", "abcdefg" };
[Benchmark]
public int MemberwiseCast()
{
// 要素ごとに (string)_data[i] なキャストが掛かる
var sum = 0;
foreach (string s in _objectData)
sum += s.Length;
return sum;
}
[Benchmark]
public int ArrayCast()
{
// 最初に1回、配列自体のキャストが掛かる
var data = (string[])_objectData;
var sum = 0;
foreach (var s in data)
sum += s.Length;
return sum;
}
public struct Wrap<T>
{
public T Value;
}
[Benchmark]
public int UnsafeStructCast()
{
// 謎の最適化。
// string 1個だけのフィールドを持つ構造体に無理やり変換して使う。
// これで倍くらい速くなる。
var data = Unsafe.As<object[], Wrap<string>[]>(ref _objectData);
var sum = 0;
foreach (var s in data)
sum += s.Value.Length;
return sum;
}
[Benchmark(Baseline = true)]
public int Static()
{
// 比較対象として、元から string[] なものを列挙
var sum = 0;
foreach (var s in _stringData)
sum += s.Length;
return sum;
}
}
public class Program
{
static void Main()
{
BenchmarkRunner.Run<ArrayDowncastBenchmark>();
}
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment