Goroutine Sayısının Sınırı: Ne Kadar Çok Açabilirsiniz
Go'da goroutine açmak çok kolay olduğu için birçok programcı 'sınırsız mı?' sorusunu sorar. Kısa cevap: hayır, ama sınır çok yüksek.
Goroutine bir işletim sistemi thread'i değildir. Go çalışma zamanı (runtime) binlerce goroutine'i az sayıda gerçek thread üzerinde zamanlamakla sorumludur. Bu tasarım, thread'lerin ağır olmasından kaynaklanır, her biri birkaç megabyte bellek tüketir. Goroutine'ler ise sadece kilobayt seviyesinde.
Teorikte milyonlarca goroutine oluşturabilirsin. Birçok kişi 10 milyon, hatta 100 milyon goroutine'nin çalıştığını test ederek ispatlamıştır. Ancak pratikte üç şey seni tutar.
Birincisi, bellek. Boş bir goroutine yaklaşık 2-3 kilobyte alır. Bir milyon goroutine açarsan 2-3 gigabyte bellek gider, ve bunlar hiçbir şey yapmıyorlar. İçlerinde veri tutarsan, kanal bağlantıları veya mutex'ler varsa, bu rakam katlanır.
İkincisi, işletim sistemi sınırları. Linux'ta dosya tanımlayıcı (file descriptor) sayısı sınırlıdır. Eğer her goroutine bir ağ bağlantısı açıyorsa, `ulimit -n` komutuyla kontrol edilen limite çarparsin. Varsayılan değer genellikle 1024 veya 65536'dır.
Üçüncüsü, CPU zamanlaması. Milyonlarca goroutine varsa, Go scheduler'ı her birine adil bir zaman dilimi vermeye çalışır. Bunu yaparken CPU tüketimi artar ve yanıt süresi bozulur.
Gerçek dünyada, iyi tasarlanmış bir sunucu uygulaması binlerce eşzamanlı bağlantıyı yönetir, goroutine başına bir bağlantı modeli. Ancak eğer goroutine'ler sürekli çalışıyorsa (örneğin sonsuz döngü), sayı düşer. Eğer goroutine'ler çoğunlukla I/O için bekliyorsa (network, veritabanı), sayı yükselir.
Praktik bir kural: başla, ölç, ayarla. Basit bir echo sunucusu 100 bin bağlantıyı rahatça tutabilir. Ama veritabanı sorgusu, dosya işlemi veya hesaplama yapan bir sunucu çok daha az goroutine'ye ihtiyaç duyar. Goroutine sayısını sınırlamak için buffered channel'lar veya semaphore deseni kullan. Unlimited pool açmak, sistemini beklenmedik bir yükün altında çökerttir.
0 yorum