Question

we're running into performance issues, and one potential culprit is a centralized use of a volatile singleton. the specific code is of the form

class foo {
  static volatile instance;
  static object l = new object();

  public static foo Instance {
    if (instance == null)
      lock(l) {
        if (instance == null)
          instance = new foo();
      }

    return foo();
  }
}

this is running on an 8-way box, and we're seeing context switching to the tune of 500,000 per second. typical system resources are fine - 25% cpu util, 25% memory util, low IO, no paging, etc.

does using a volatile field induce a memory barrier or any kind of cpu cache reload? or does it just go after main memory every time, for that field only?

Was it helpful?

Solution

lock does induce a memory barrier, so if you are always accessing instance in a lock you don't need the volatile.

According to this site:

The C# volatile keyword implements acquire and release semantics, which implies a read memory barrier on read and a write memory barrier on write.

OTHER TIPS

One thing volatile will not do is cause a context switch. If you're seeing 500,000 context switches per second, it means that your threads are blocking on something and volatile is not the culprit.

Sadly, the singleton takes a bad rap for just about everything :)

This isn't my domain of expertise, but as far as I know there's nothing special about volatile other than the compiler/run-time NOT re-ordering read/writes (to the variable) for optimization purposes.

Edit: I stand corrected. Not only does volatile introduce memory barriers, but what goes on (and incidentally, performance) depends largely on the particular CPU involved. See http://dotnetframeworkplanet.blogspot.com/2008/11/volatile-field-and-memory-barrier-look.html

This is why you still need the lock.

Questions which may/may not have been answered already:

  1. What is your singleton instance actually doing? Maybe the instance code needs to be refactored...
  2. What's the thread count of the running process? An 8 way box won't help you if you have an abnormally high thread count.
  3. If it's higher than expected, why?
  4. What else is running on the system?
  5. Is the performance issue consistent?

In your example here, volatile should not be the subject of any "slowdown". The lock() however, can involve huge roundtrips to the kernel, especially if there's a lot of contention for the lock.

There is really no need to lock your singleton in this case, you could just do

class Foo {
  static Foo instance = new Foo();
  public static Foo FooInstance() {
    return instance ;
  }
}

Ofcourse, if 'instance ' is used in a lot of different threads, you'd still have to lock() anything that alters that Foo, unless all methods/properties of Foo is readonly. e.g.

 class Foo {
      static Foo instance = new Foo();
      object l = new object();
      int doesntChange = 42;
      int canChange = 123;
      public static Foo FooInstance() {
        return instance ;
      }
      public void Update(int newVal) {
         lock(l) { // you'll get a lot of trouble without this lock if several threads accesses the same FOO. Atleast if they later on read that variable 
            canChange = newVal;
         }

      public int GetFixedVal() {
         return doesntChange; //no need for a lock. the doesntChange is effectivly read only
      }
    }

There's really no need for the use of volatile for a singleton, as you're setting it exactly once - and locking the code the sets it. See Jon Skeet's article on singletons for more info.

The short answer is, Yes it creates a memory barrier (flushes everything and goes to main memory, not just that single variable), but No it will not be the cause of context switching.

Also, as others have mentioned, I don't believe volatile is necessary here.

Licensed under: CC-BY-SA with attribution
Not affiliated with StackOverflow
scroll top