0

Does use of Singleton / Static slows down Multi-Threaded Application (running on multi-core system)? I was running an application creating 6 threads on 8 core machine. Initially a few singleton objects shared among all the thread. And I was not getting the the expected performance boost for going from single-threaded to multi-threaded model. After this I change my code so that there is no singleton or static (i.e tried not to share anything among the threads) and I got a performance boost of approx 6 times. Can somebody please explain the behavior?

  • 5
    I think we need to see some code to answer that. If you have a lot of contention for synchronized resources, multi-threading won't help you much, and might even hurt you. – Keppil May 30 '13 at 07:25

2 Answers2

4
  1. static has definitely nothing to do with slowdowns. In fact, static fields are the fastest of all to access.

  2. Singletons by themselves are not an issue either. You may have lazily initialized singletons, whose accessor methods are synchronized. In this case your code ss just using the wrong idiom. The idiom of choice for static singletons is the lazy initialization holder class, which incurs zero penalty and is completely thread-safe.

  3. It may also be the case that the methods you call on singletons need synchronization. Usually, if we are using mutable singletons at all, it is because we have no choice but to use them. If you do have such choice, then by all means avoid singletons.

For optimum performance, uphold these simple rules:

  1. share as little mutable state as possible. Mutation needs mutual exclusion and hurts performance;

  2. share as much immutable state as possible. This will reduce CPU cache misses and improve performance.

Marko Topolnik
  • 195,646
  • 29
  • 319
  • 436
  • The lazy initialization holder class has been covered on [SO](http://stackoverflow.com/questions/8297705/how-to-implement-thread-safe-lazy-initialization) before, including sample code. – Andrew Lazarus May 30 '13 at 07:40
  • 2
    @AndrewLazarus *Everything* has already been covered on SO :) Anyway, I have may own favorite reference for the LIHC, from the horse's mouth (see my link). – Marko Topolnik May 30 '13 at 07:42
  • Marko: Thank you for adding that link to the original answer. I just wanted the OP to see sample code. – Andrew Lazarus May 30 '13 at 07:46
  • @AndrewLazarus I was planning for that link all along, but wanted to write out the answer first and then search for the link. – Marko Topolnik May 30 '13 at 07:47
  • Thanks. Two quick points: (i) My singleton was eagerly initialized (no synchronization used anywhere in the application). (ii) It was state less and therefore immutable. What I suspected was in case of singleton parallelism is not efficiently achieved in multi-core system. – Abhinava Srivastava May 31 '13 at 07:44
  • If anything, sharing an immutable, `static final` singleton should result in more efficiency, sequential and parallel alike. I suspect that you have not properly identified the exact aspect of the changes you made to the code, which are responsible for performance increase. – Marko Topolnik May 31 '13 at 08:00
  • Thanks for the pointer - 'CPU cache misses'. [this](http://stackoverflow.com/questions/14096960/optimising-java-objects-for-cpu-cache-line-efficiency) suggests cache line efficiency is hard to achieve in java because of large object graph. In my case there were many shared stateless but complex (singleton) caches shared among the threads. – Abhinava Srivastava May 31 '13 at 10:58
1

There are many issues with stateful singletons, but what you are describing sounds more like contention for the singleton object. That is, you had a slowdown because your singleton(s) were synchronizing on something. In that case, the multi-threaded version may not be doing the same thing; that is, you may have traded a performance problem for a race condition. You need to show us more detail of your code for a more specific answer. As is, pretty much just guessing.

BTW, IMHO stateless singletons are best handled as enum.

Community
  • 1
  • 1
Andrew Lazarus
  • 18,205
  • 3
  • 35
  • 53
  • I agree with @Andrew - this sounds like contention, particularly as the performance boost is approximately equal to the number of threads you employ. I think we need to see some code, but it does sound like you may have overdone it with your use of the synchronized keyword – DaveH May 30 '13 at 07:35