Tek thread ile çalışmanın avantaj ve dezavantajları
Önceki bir flood’da JavaScript’in tek thread (single thread
) ile işleri nasıl eş zamanlı yürüttüğüne değinmiştik. Bu flood'da ise tek thread ile çalışmanın bazı avantaj ve dezavantajlarını ele alacağız.
İşletim sistemleri, işlemciyi çalışan uygulamalar arasında belirlenen bir planlama algoritması (Round Robin Scheduling
, Priority Based Scheduling
, vb) ile paylaştırarak bütün proseslerin işlemciyi kullanmasını sağlarlar. Seçilecek planlama algoritması (Scheduling Algorithm
) sistemin tipine göre belirlenir. Round Robin
ile uygulamalara eşit olarak dağıtılan işlemci zamanı Priority Based
ile uygulamaların önceliklerine göre kullandırılır. Gerçek Zamanlı
sistemlerde Priority Based Scheduling
kullanılır çünkü sistemin asıl işi önceliklendirilir.
İşletim sistemleri, Scheduler
adı verilen bileşenler ile Scheduling
işlevini yürütürler. Scheduling
işlemi temel olarak, Scheduler
'ın işlemci üzerinde koşmakta olan ve kendisine ayrılan süre dolan thread'i uyutarak, koşmaya hazır başka bir thread'e işlemciyi vermesidir. Scheduler
zamanı dolan thread'i uyuturken onun state
'ini (register
, SP - stack pointer
, PC - program counter
, TLB - memory map
, vb) kaydedip, koşmaya hazırlanan thread'in state
'ini yükler, bu işlem Context Switch
olarak adlandırılır ve maliyetli bir işlemdir.
Linux’ta, thread’ler de proses’lere benzer şekilde koşturulur. Aynı proses içindeki iki thread bazı memory alanlarını ortak kullandığından dolayı işlemci aynı proses içindeki iki thread arasında el değiştirirken oluşan Context Switch
maliyeti işlemcinin iki farklı proses arasında el değiştirme maliyetinden küçüktür. Bundan dolayı, eğer proseslerin sağladığı izolasyon gerekli değilse kaynakların etkin kullanımı açısından uygulama tasarımında multi-prosess
yerine multithreaded
yaklaşımın benimsenmesi anlamlı olacaktır.
Yukarıdaki uzun girizgahtan da anlaşılacağı üzere single-threaded
çalışmanın en önemli avantajlarından biri işlerin tek thread ile yürümesi dolayısıyla Context Switch
yükünün (overhead
) ortadan kalkmasıdır. Özellikle eş zamanlı çalışan thread sayısının oldukça arttığı durumlarda (> 100
) Context Switch
'e harcanan zaman işlemci zamanının önemli bir kısmını almaya başlayacak ve verimli olarak kullanılabilecek bu işlemci zamanı thread'ler arasında geçiş yapmak üzere harcanacaktır.
Single-threaded
uygulama tasarımında önceki flood'da bahsedilen Run-to-Completion
özelliği ile birlikte, aynı anda sadece bir thread işini bitirene kadar koştuğu için semaphore
, lock
benzeri race condition
önleyici senkronizasyon yapıları kullanmak gerekmez. Bu sayede uygulamada daha az senkronizasyon kaynaklı programlama hatası ortaya çıkar. Örnek olarak Mars keşif aracı PathFinder
tek thread ile çalışsaydı önceki bir flood'da anlatıldığı gibi Priority Inversion
problemi ile karşılaşmayacaktı. https://medium.com/@gokhansengun/5b6ebe771d55
Single-threaded
sistemlerin en önemli dezavantajlarından biri uygulamanın kooperatif biçimde çalışmasına bel bağlamasıdır. İşlemcinin koşturduğu kod bloğunun çalışması bitmeden başka bir kod koşturulamayacağından uygulamadaki bir sonsuz döngü bütün uygulamayı kilitleyebilir. Benzer durum multithreaded
uygulamada sadece ilgili thread'in işlev gösterememesi ve işlemci kaynaklarının gereksiz kullanımı ile genel sistem yavaşlaması ile atlatılabilecekken single-threaded
bir uygulamada uygulamanın bir bütün olarak işlevsiz kalmasına neden olur.
Anlaşılacağı üzere Real Time
uygulamalarda single-threading
kullanılamaz çünkü bu tip uygulamalarda sistemin gerçek zamanlı olarak tepki vermesi gereken işlemler vardır. Örneğin bir arabanın fren sistemini kontrol eden elektronik devrenin birkaç milisaniye içinde aktive edilmesi gereken bir durumda single-thread
'in o anda koşturmakta olduğu ve 20 milisaniye sürecek CD çalardan sonraki şarkıyı yükleme işlemi beklenemez. Dolayısıyla aslında Mars keşif aracı PathFinder
'da tek thread'li bir mimari kullanmak mümkün değildir :-)
Tek thread olarak çalışan uygulamaları popüler hale getiren ve muhtemelen bu flood’u yazdıran özellikleri ise I/O ağırlıklı, yani veri alış verişinin yoğun olduğu uygulamalarda oldukça iyi ölçeklenebilmeleridir. Web sunucular, proxy sunucular ve uygulama sunucular genellikle I/O ağırlıklı uygulamalardır. I/O ağırlıklı uygulamalar hızlı bir veri işlemeden sonra girdi/çıktı bekledikleri için ve bu kısa işlemler arasında işlemci üzerinde Context Switch
oluşturmadıkları için yüksek yüklerde çok iyi biçimde performans göstermektedirler.
CPU ağırlıklı işlemlerde (video işleme, matematiksel işlemler, vb) ise tek thread olarak çalışan uygulamaların ölçekleme özellikleri anlamını kaybeder, aksine tek thread uzun süreler boyunca kullanıldığı için kullanıcı deneyimi olumsuz anlamda etkilenir. Tek thread ile çalışan birçok sistem CPU ağırlıklı işlemlerin yapılabilmesi için farklı mekanizmalar sunmaktadır. Tarayıcılarda, JavaScript’in CPU ağırlıklı işlemlerin yapılabilmesi için Web Worker
'lar kullanıma sunulmuştur.
Modern bilgisayarlarda birden fazla işlemci ve her işlemcide bir veya birden fazla çekirdek (core
) bulunur. Tek thread'li uygulamalar ek bir efor olmadan çok çekirdekli mimariden istifade edemezler. Tek bir thread çalıştığı için aynı anda sadece bir çekirdek kullanabilirler. Özellikle sunucu tarafındaki uygulamalarda (JavaScript
için Node.js
) bütün çekirdekleri kullanmak performans açısından elzem olduğu için sunucuda çekirdek sayısı kadar Node.js
uygulaması çalıştırılır ya da uygulama içerisinde core sayısı kadar worker yaratılır.
Web sunucu ve proxy sunucu olarak popüler olarak kullanılan Nginx
de single-threaded
olarak çalışmaktadır. Nginx
, default konfigürasyonunda worker_processes auto;
ile koşturulduğu sunucudaki çekirdek sayısı kadar worker
proses açarak istekleri bu proseslerle karşılar.
single-threaded
olarak çalışan Nginx
'in, multithreaded
olarak çalışan Apache
web sunucu ile eş zamanlı 50 kullanıcıyla 5k'lık bir dosya istenerek yapılan karşılaştırması aşağıda bulunabilir. https://bit.ly/2eERS8V
Son olarak, JavaScript’in işleri tek thread ile nasıl paralel yürüttüğünü anımsamak için önceki bu flood’a https://medium.com/@gokhansengun/24f92f71f9bd göz atabilirsiniz.