Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

How to avoid slowdown due to locked code?

Tags:

performance

c#

I am wondering how a piece of locked code can slow down my code even though the code is never executed. Here is an example below:

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;
}

This code runs in ~1300ms on my machine. If we remove the lock block (but keep its body), we get 750ms. Almost the double, even though the code is never run!

Of course this code does nothing. I noticed it while adding some lazy initialization in a class where the code checks if the object is initialized and if not initializes it. The problem is that the initialization is locked and slows down everything even after the first call.

My questions are:

  1. Why is this happening?
  2. How to avoid the slowdown
like image 743
pieroxy Avatar asked May 06 '13 10:05

pieroxy


People also ask

Is lock slow?

Locks (also known as mutexes) have a history of being misjudged. Back in 1986, in a Usenet discussion on multithreading, Matthew Dillon wrote, “Most people have the misconception that locks are slow.” 25 years later, this misconception still seems to pop up once in a while.

Does slow down code?

No the compiler does not slow down the program, it ignores all the comments and takes the raw code. Show activity on this post. If language is using the compiler then the processing don't effected but if interpreter is working there then the process may slow down due to comments.

What does lock () return when a the lock is being held?

While a lock is held, the thread that holds the lock can again acquire and release the lock. Any other thread is blocked from acquiring the lock and waits until the lock is released. Since the code uses a try... finally block, the lock is released even if an exception is thrown within the body of a lock statement.

Is lock expensive C#?

lock (Monitor. Enter/Exit) is very cheap, cheaper than alternatives like a Waithandle or Mutex.


1 Answers

About why it's happening, it has been discussed in the comments : it's due to the initialization of the try ... finally generated by the lock.


And to avoid this slowdown, you can extract the locking feature to a new method, so that the locking mechanism will only be initialized if the method is actually called.

I tried it with this simple code :

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

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

And here are my times (in ticks) :

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

EDIT : My test code (running a bit slower than the code with no locks) was actually on static methods, it appears that when the code is ran "inside" an object, the timings are the same. I fixed the timings according to that.

like image 177
Zonko Avatar answered Sep 28 '22 03:09

Zonko