http://cocoasamurai.blogspot.com/search/label/%5Bat%5Dsynchronized%20Lock

Tuesday, April 15, 2008

OSSpinLock :: Lock Showdown ( POSIX Locks vs OSSpinLock vs NSLock vs @synchronized )

Reader Simon Chimed in on my Last article about threading in Leopard:

Worth mentioning as well is the OSSpinLock{Lock, Unlock} combination; these busy-wait, but are by far the cheapest to acquire/release. In the case of many resources and lightweight access (very few threads, and/or little work being done per access), they may pay off significantly.

Consider the set/get methods for 10000 objects. Creating an OSSpinLock for each object is cheap (it's just an int), and if the likelihood of access to an given object is small (ie, there's not 1 object constantly being accessed and 9999 very rarely), the OSSpinLock approach (implemented by memory barriers, IIRC) can really pay off, because the cross-section of thread conflict is minute.


Thanks for adding to the Discussion Simon, I did forget to include OSSpinLock. And he is right, buried inside the libkern/OSAtomic.h header is the OSSpinLock API. OSSpinLock can be a particularly fast lock, however the Apple Man Page on it makes it clear that it is best used when you expect little lock contention. I started to develop a test to gauge this performance till I discovered that someone had already developed one for this purpose on CocoaDev, however it left out @synchronized() so I took the test and extended it to add @synchronized and see how fast OSSpinLock was and how much we really pay for using @synchronized().

The test creates and gets 10,000,000 objects while using locks in the form of POSIX Mutex Locks, POSIX RWLock/unlock, OSSpinLock, NSLock (which uses POSIX locking) and the @synchronized() lock. I ran the test several times over and grabbed a snapshot which reflected what I got on the 3rd run and showed the (about) average results I got before and after this run. The graph shows the time per request which was derived from dividing the total requests by the time it took to complete all 10,000,000 objects for setting or getting. This was run on my 2.33 GHz Core 2 Duo Mac Book Pro with 2 GB RAM.

lock_showdown.png

lock_showdown_results.png


Results are in usec's. As you can see OSSpinLock is the fastest in this instance, but not by much when compared to the POSIX Mutex Lock. Also seen above we can see the pain that Google Described with regard to performance when using the @synchronized directive. When you run the test it's painfully obvious even from a user perspective that @syncrhonized does cost you in terms of performance relative to the other locking methods. Where the other locks take about 2 or (at most 3 seconds) to complete the test @synchronized takes 4 or 5 seconds to accomplish the same task. Here at the total runtimes for the tests

POSIX Mutex Lock (Set): 2.382080 Seconds
POSIX RW Lock (Set): 2.881769 Seconds
OSSpinLock (Set): 2.278029 Seconds
NSLock (Set): 2.948313 Seconds
@Synchronized (Set): 4.310732

POSIX Mutex Lock (Get): 2.953534 Seconds
POSIX RW Lock (Get): 3.390998 Seconds
OSSpinLock (Get): 2.880452 Seconds
NSLock (Get): 3.493390 Seconds
@Synchronized (Get): 5.098508 Seconds

Ouch! Things aren't looking good for @synchronized at this point. However in terms of a compromise for speed and efficiency I particularly like the POSIX Mutex Lock the best, because (as stated on CocoaDev) it already tries a spin lock first (which doesn't call into the kernel (why OSSpinLock is so fast here)) and only goes to the kernel when a lock is already taken by another thread. Which means in a best case scenario it is basically acting exactly like OSSpinLock and it doesn't have any of the disadvantages to OSSpinLock. OSSpinLock has to poll every so often checking to see if its resource is free which (as stated earlier) doesn't make it an attractive option when you expect some lock contention.

Still Simon is right in that depending on how your application works OSSpinLock can be an attractive option to employ in your app and is something worth looking into. This isn't a "this one is the best!" type of thing, it's (as I've said before) something you have to test and see if it's right for you.

Reply via email to