お気に入りのプロジェクトの 1 つとして、7 カード ポーカーのハンド評価を書いています。その速度を最適化しようとしている間 (私はその挑戦が好きです)、Dictionary キー検索のパフォーマンスが配列インデックス検索と比較して非常に遅いことにショックを受けました。
たとえば、52 の choose 7 = 133,784,560 の可能な 7 枚のカード ハンドすべてを列挙するこのサンプル コードを実行しました。
var intDict = new Dictionary<int, int>();
var intList = new List<int>();
for (int i = 0; i < 100000; i ++)
{
intDict.Add(i, i);
intList.Add(i);
}
int result;
var sw = new Stopwatch();
sw.Start();
for (int card1 = 0; card1 < 46; card1++)
for (int card2 = card1 + 1; card2 < 47; card2++)
for (int card3 = card2 + 1; card3 < 48; card3++)
for (int card4 = card3 + 1; card4 < 49; card4++)
for (int card5 = card4 + 1; card5 < 50; card5++)
for (int card6 = card5 + 1; card6 < 51; card6++)
for (int card7 = card6 + 1; card7 < 52; card7++)
result = intDict[32131]; // perform C(52,7) dictionary key lookups
sw.Stop();
Console.WriteLine("time for dictionary lookups: {0} ms", sw.ElapsedMilliseconds);
sw.Reset();
sw.Start();
for (int card1 = 0; card1 < 46; card1++)
for (int card2 = card1 + 1; card2 < 47; card2++)
for (int card3 = card2 + 1; card3 < 48; card3++)
for (int card4 = card3 + 1; card4 < 49; card4++)
for (int card5 = card4 + 1; card5 < 50; card5++)
for (int card6 = card5 + 1; card6 < 51; card6++)
for (int card7 = card6 + 1; card7 < 52; card7++)
result = intList[32131]; // perform C(52,7) array index lookups
sw.Stop();
Console.WriteLine("time for array index lookups: {0} ms", sw.ElapsedMilliseconds);
出力:
time for dictionary lookups: 2532 ms
time for array index lookups: 313 ms
このタイプの動作は予想されますか (パフォーマンスが 8 分の 1 に低下します)。IIRC では、ディクショナリには平均で O(1) ルックアップがあり、配列には最悪の O(1) ルックアップがあるため、配列ルックアップが高速になると期待していますが、それほどではありません!
現在、ポーカーハンドのランキングを辞書に保存しています。これが辞書検索と同じくらい速い場合は、アプローチを再考して代わりに配列を使用する必要があると思いますが、ランキングのインデックス作成は少し難しくなり、おそらくそれについて別の質問をする必要があります.