スレッドセーフのコスト
マルチスレッド対応するには同期させる必要があります。.NETではその為に、幾つかの手段を提供していますが、パフォーマンス面でどのような差があるのでしょうか?
using System; using System.Threading; using System.Runtime.CompilerServices; class TheClass { const int LEN = 14; const int LOOP = 10000000; public int num; // ロックなし public void Inc() { ++num; } // ロックあり public void IncLockThis() { lock (this) { ++num; } } // インクリメント/デクリメント専用 public void Incerlocked() { Interlocked.Increment(ref num); } // 同期メソッド [MethodImpl(MethodImplOptions.Synchronized)] public void IncMethodImpl() { ++num; } static void Main(string[] args) { DateTime t; TheClass the = new TheClass(); t = DateTime.Now; for (int i = 0; i < LOOP; ++i) the.Inc(); Console.WriteLine("{0} : {1}", "Inc".PadRight(LEN), DateTime.Now - t); t = DateTime.Now; for (int i = 0; i < LOOP; ++i) the.IncLockThis(); Console.WriteLine("{0} : {1}", "IncLockThis".PadRight(LEN), DateTime.Now - t); t = DateTime.Now; for (int i = 0; i < LOOP; ++i) the.Incerlocked(); Console.WriteLine("{0} : {1}", "Incerlocked".PadRight(LEN), DateTime.Now - t); t = DateTime.Now; for (int i = 0; i < LOOP; ++i) the.IncMethodImpl(); Console.WriteLine("{0} : {1}", "IncMethodImpl".PadRight(LEN), DateTime.Now - t); } } /* 結果 Inc : 00:00:00.1718750 IncLockThis : 00:00:00.6562500 Incerlocked : 00:00:00.2500000 IncMethodImpl : 00:00:00.5468750 */
lockよりMethodImplOptions.Synchronizedの方が僅かにパフォーマンスが良いみたいです。ところで、日記上でパフォーマンスネタを良く取り上げてますが、これはネタとして扱いやすいこともありますが、それよりも.NET上でのパフォーマンスについての感覚を身につけるためだったりします。C/C++ならある程度想像がついたんですが、.NETだとまだまだ読み切れないところが多くて・・・