SpinLock & Mutex Karşılaştırması
Mutex kullanımlarının performans problemi yaratabileceği senaryolar mevcuttur.
Örnek olarak A ve B thread'lerinin bir mutex kaynağını kilitleyip, çok hızlı biçimde işlemi gerçekleştirip kilidi kaldırdığını, bu işlemi de saniyede binlerce veya yüzbinlerce defa yaptığını düşünelim.
Mutex operasyonları context-switch gerektirdiğinden kilitli kalma süresi çok az olsa da bir yerden sonra her bir kilitleme işleminde thread'in Sleep durumuna geçmesi sonra tekrar uyandırılması sürecinin kendisi zaman alıcı bir işleme dönüşür.
Böyle bir durumda mutex kullanmak yerine spinlock kullanımı daha avantajlı olur.
Spinlock kullanıcı kipinde busy wait ile gerçekleştirilir. Dolayısıyla ilgili thread Sleep moduna geçmez, context-switch gerçekleşmez ve kullanıcı kipinde kendisine tahsis edilen cpu zamanını sonuna kadar kullanabilmiş olur.
Ancak eğer ilgili uygulama cpu kullanmaya devam ederek beklediği spinlock'a çok hızlı bir şekilde erişemez ise bu defa tersi bir etki yaratır ve Sleep moduna geçmesi halinde aynı zaman diliminde CPU ile başka bir işlem yapılabilecekken, bu imkan ortadan kalkar ve CPU yükünün artmasına neden olur.
Dolayısıyla spinlock kullanımının tüm senaryolarda daha iyi sonuç verecek olduğunu söylemek çok yanlış olur.
Dahası spinlock kullanımı özellikle Linux mutex performansının çok iyileştirilmiş olmasından ötürü, pek çok senaryoda mutex kullanımının daha iyi sonuç vermesini sağlar. Emin değilseniz, risk almayın, mutex kullanın.
Probleminizi iyi tanıdıysanız ve spinlock kullanımını iyice test ettiyseniz kullanabilirsiniz.
Aşağıdaki örnek uygulama kodunu locktest.c
adıyla kaydedin. Normal mutex versiyonunu ek bir parametre vermeden, Spinlock versiyonunu -DUSE_SPINLOCK
parametresiyle aşağıdaki gibi derleyip 100 milyon loop parametresi ile çalıştırıp işlem süresini ölçün.
Teste başlamadan önce Cpu Frequency Scaling aktif ise işlemci hızını aşağıdaki gibi maksimuma ayarlayıp, bu sebeple sonuçlarda oluşacak ek dalgalanmayı bertaraf etmeniz de önerilir (işlemin tüm cpu çekirdekleri için tekrar edilmesi gereklidir):
Şimdi normal mutex ve spinlock versiyonlarını derleyelim:
Her iki uygulamayı 100 milyon loop için aşağıdaki gibi çalıştırdığımızda performans farklılıklarını görebiliriz:
Testleri bir kaç defa daha üstüste çalıştırdığımızda bir miktar değişiklikler görebiliriz ancak normal mutex versiyonu, spinlock kullanan versiyondan en az 2 kat daha yavaş çalışmaktadır.
Hibrid Yaklaşım
Bu senaryo için spinlock'un daha iyi olduğunu gördük. Bir çok senaryo için de mutex kullanımının toplam sistem performansı için daha olumlu olacağını söyledik.
POSIX standardında her iki yaklaşımı birden kullanan hibrid bir modele de yer verilmiş olup Linux NPTL implementasyonunda böyle bir kullanım da desteklenmektedir.
Hibrid modelde mutex lock işlemi önce spinlock kullanılarak (try_lock mekanizmalarıyla) maksimum N defa denenenir (bu değerin hesaplaması glibc içerisinde mevcuttur). Ardından spinlock ile elde edilemiyorsa bu defa geleneksel mutex lock modeline geri dönülür.
Elbette hibrit modelin de tüm senaryolara uygulanabileceğini söylemek doğru olmaz. Spinlock kullanım avantajlarını hiç üretemeyen bir yazılım akışınız var ise, hibrid mod da performans kaybına yol açacaktır.
Hibrid modun kullanılabilmesi için, mutex initialize işleminde PTHREAD_MUTEX_ADAPTIVE_NP
tipinin seçilmiş olması gereklidir.
Yukarıdaki örnek uygulamamızın -DUSE_HYBRID
parametresiyle üçüncü bir versiyonunu derleyip test edelim:
Görüldüğü üzere doğrudan spinlock kullandığımız versiyona oranla biraz daha kötü ama ona çok yakın bir değer elde etmiş olduk.
Last updated
Was this helpful?