18

コードが実行されていないにもかかわらず、ロックされたコードの一部がどのように私のコードを遅くすることができるのか疑問に思っています。以下に例を示します。

public void Test_PerformanceUnit()
{
    Stopwatch sw = new Stopwatch();
    sw.Start();
    Random r = new Random();
    for (int i = 0; i < 10000; i++)
    {
        testRand(r);
    }
    sw.Stop();
    Console.WriteLine(sw.ElapsedTicks);
}

public object testRand(Random r)
{
    if (r.Next(1) > 10)
    {
        lock(this) {
            return null;
        }
    }
    return r;
}

このコードは、私のマシンで 1300 ミリ秒以内に実行されます。ロック ブロックを削除すると (本体はそのまま)、750ms になります。コードが実行されることはありませんが、ほぼ 2 倍です。

もちろん、このコードは何もしません。コードがオブジェクトが初期化されているかどうかをチェックし、そうでない場合は初期化するクラスに遅延初期化を追加しているときに気づきました。問題は、初期化がロックされ、最初の呼び出しの後でもすべてが遅くなることです。

私の質問は次のとおりです。

  1. なぜこうなった?
  2. 速度低下を回避する方法
4

1 に答える 1

10

なぜそれが起こっているのかについては、コメントで議論されています:try ... finallyによって生成されたの初期化が原因lockです。


この速度低下を回避するために、ロック機能を新しいメソッドに抽出して、メソッドが実際に呼び出された場合にのみロック メカニズムが初期化されるようにすることができます。

私はこの簡単なコードでそれを試しました:

public object testRand(Random r)
{
    if (r.Next(1) > 10)
    {
        return LockingFeature();
    }
    return r;
}

private object LockingFeature()
{
    lock (_lock)
    {
        return null;
    }
}

そして、これが私の時間です(ティック単位):

your code, no lock   : ~500
your code, with lock : ~1200
my code              : ~500

編集: 私のテスト コード (ロックなしのコードよりも少し遅く実行) は、実際には静的メソッド上にありました。コードがオブジェクトの「内部」で実行された場合、タイミングは同じです。それに合わせてタイミングを調整しました。

于 2013-05-06T12:53:32.537 に答える