Twisted'deki seçme / anket ve epoll reaktörlerinin uyarıları


95

Okuduğum ve deneyimlediğim her şey (Tornado tabanlı uygulamalar), ePoll'un özellikle Twisted ile Seç ve Anket tabanlı ağın doğal bir alternatifi olduğuna inanmamı sağlıyor. Bu da beni paranoyak yapıyor, daha iyi bir tekniğin veya metodolojinin bir bedeli olmaması oldukça nadirdir.

Epoll ve alternatifler arasındaki birkaç düzine karşılaştırmayı okumak, epoll'ün açıkça hız ve ölçeklenebilirlik şampiyonu olduğunu, özellikle de fantastik olan doğrusal bir şekilde ölçeklendiğini gösteriyor. Bununla birlikte, işlemci ve bellek kullanımı konusunda epoll hala şampiyon mu?

Yanıtlar:


191

Çok az sayıda soket için (elbette donanımınıza bağlı olarak değişir, ancak 10 veya daha az olan bir şeyden bahsediyoruz), bellek kullanımı ve çalışma süresi hızında epoll'ü seçin. Tabii ki, bu kadar az sayıda soket için, her iki mekanizma da o kadar hızlıdır ki, çoğu durumda bu farkı gerçekten önemsemezsiniz.

Yine de bir açıklama. Doğrusal olarak hem seçim hem de epoll ölçeği. Bununla birlikte, büyük bir fark, kullanıcı alanına yönelik API'lerin farklı şeylere dayanan karmaşıklıklara sahip olmasıdır. Bir selectaramanın maliyeti kabaca, onu ilettiğiniz en yüksek numaralı dosya tanımlayıcısının değerine göre değişir. Tek bir fd (100) seçerseniz, bu, tek bir fd olan 50'yi seçmekten kabaca iki kat daha pahalıdır. En yüksek değerin altına daha fazla fds eklemek tamamen ücretsiz değildir, bu nedenle pratikte bundan biraz daha karmaşıktır, ancak bu çoğu uygulama için iyi bir ilk yaklaşımdır.

Epoll'un maliyeti, gerçekte üzerlerinde olaylar bulunan dosya tanımlayıcıların sayısına daha yakındır. 200 dosya tanımlayıcısını izliyorsanız, ancak bunlardan yalnızca 100 tanesinde olay varsa, o zaman (çok kabaca) yalnızca bu 100 etkin dosya tanımlayıcısı için ödeme yaparsınız. Epoll, seçime göre en büyük avantajlarından birini sunma eğiliminde olduğu yer burasıdır. Çoğunlukla boşta olan bin müşteriniz varsa, seç seçeneğini kullandığınızda hala bin müşterinin tamamı için ödeme yaparsınız. Bununla birlikte, epoll ile, sanki sadece birkaç tane varmış gibi - herhangi bir zamanda sadece aktif olanlar için ödeme yaparsınız.

Tüm bunlar, epoll'un çoğu iş yükü için daha az CPU kullanımına yol açacağı anlamına gelir. Bellek kullanımı söz konusu olduğunda, biraz yükseliyor. selectgerekli tüm bilgileri oldukça kompakt bir şekilde temsil etmeyi başarır (dosya tanımlayıcısı başına bir bit). Ve kaç dosya tanımlayıcısıyla birlikte kullanabileceğinize ilişkin FD_SETSIZE (tipik olarak 1024) sınırlaması, birlikte kullanabileceğiniz selectüç fd kümesinin her biri için asla 128 bayttan fazla harcamayacağınız anlamına gelir.select(oku, yaz, istisna). Maksimum 384 bayt ile karşılaştırıldığında, epoll bir çeşit domuz. Her dosya tanımlayıcısı, çok baytlı bir yapı ile temsil edilir. Bununla birlikte, mutlak terimlerle, yine de fazla bellek kullanmayacak. Çok sayıda dosya tanımlayıcısını birkaç düzine kilobaytta temsil edebilirsiniz (sanırım 1000 dosya tanımlayıcısı başına kabaca 20k). Ayrıca, selectyalnızca bir dosya tanımlayıcısını izlemek istiyorsanız, ancak değeri 1024 ise, bu baytların 384'ünü de harcamanız gerektiği gerçeğini de atabilirsiniz, epoll ile yalnızca 20 bayt harcarsınız. Yine de, tüm bu sayılar oldukça küçük, bu yüzden pek bir fark yaratmıyor.

Ayrıca epoll'un belki de zaten bildiğiniz başka bir faydası da FD_SETSIZE dosya tanımlayıcıları ile sınırlı değildir. Sahip olduğunuz kadar çok dosya tanımlayıcısını izlemek için kullanabilirsiniz. Ve eğer sadece bir dosya tanımlayıcınız varsa, ancak değeri FD_SETSIZE'den büyükse, epoll bununla da çalışır, ancak selectçalışmaz.

Rastgele olarak, yakın zamanda veya ile epollkarşılaştırıldığında küçük bir dezavantaj keşfettim . Bu üç API'nin hiçbiri normal dosyaları (yani, bir dosya sistemindeki dosyaları) desteklemese de ve bu destek eksikliğini, bu tür tanımlayıcıları her zaman okunabilir ve her zaman yazılabilir olarak rapor etmek olarak gösterir. Bu, engellemeyen herhangi bir anlamlı dosya sistemi G / Ç türü için onları uygunsuz kılar , dosya sisteminden bir dosya tanımlayıcı kullanan veya karşılaşan bir program en azından çalışmaya devam eder (veya başarısız olursa, çünkü arasında ya ), buna da olsa belki de en iyi performansı.selectpollselectpollselectpollselectpoll

Öte yandan, böyle bir dosya tanımlayıcısını izlemesi istendiğinde epollbir hatayla ( EPERMgörünüşe göre) hızlı bir şekilde başarısız olur . Açıkçası, bu pek de yanlış değil. Sadece açıkça destek eksikliğini işaret ediyor. Normalde açık başarısızlık durumlarını alkışlardım, ancak bu belgelenmemiş (söyleyebildiğim kadarıyla) ve yalnızca potansiyel olarak düşük performansla çalışan bir uygulama yerine tamamen bozuk bir uygulama ile sonuçlanıyor.

Pratikte, bunun ortaya çıktığını gördüğüm tek yer, stdio ile etkileşime girerken oldu. Bir kullanıcı stdin veya stdout'u normal bir dosyadan / dosyaya yönlendirebilir. Önceden stdin ve stdout, epoll tarafından gayet iyi desteklenen bir boru şeklindeyken, normal bir dosya haline gelir ve epoll yüksek sesle başarısız olur ve uygulamayı bozar.


Çok güzel cevap. Bütünlük için davranış konusunda açık olmayı pollmı düşünüyorsunuz?
quark

6
Sıradan dosyalardan okuma davranışına dair iki sentim: Genelde, performans düşüşüne doğrudan başarısızlığı tercih ederim. Bunun nedeni, geliştirme sırasında tespit edilme olasılığının çok daha yüksek olması ve bu nedenle uygun şekilde çalışılmasıdır (örneğin, gerçek dosyalar için G / Ç'yi yapmak için alternatif bir yönteme sahip olarak). Elbette YMMV: gözle görülür bir yavaşlama olmayabilir, bu durumda başarısızlık daha iyi değildir. Ancak, yalnızca özel durumlarda meydana gelen dramatik yavaşlamayı geliştirme sırasında yakalamak çok zor olabilir ve gerçekten konuşlandırıldığında onu bir saatli bomba olarak bırakır.
quark

1
Sadece düzenlemenizi tamamen okumalısınız. Bir bakıma epoll'un öncüllerini taklit etmemesinin muhtemelen doğru olmadığı konusunda hemfikirim, ancak daha sonra EPERM hatasını uygulayan devin "Sırf her zaman bozuk olduğu için benimkini kırmayı doğru yapmaz, çünkü iyi." Ve yine bir başka karşı argüman, savunmacı bir programcıyım, 1 + 1'i geçen her şey şüpheli ve zarif başarısızlıklara izin verecek şekilde kodluyorum. Çekirdeğin ateşlenmesi beklenmedik bir hata hoş veya düşünceli değildir.
David

1
@ Jean-Paul, kqueue hakkında da bir açıklama ekleyebilir misiniz?
Good Person

Performansı bir kenara koyarsak, bundan (kaynaklı man select) kaynaklanan bir sorun var mı Linux çekirdeği sabit bir sınır getirmez, ancak glibc uygulaması fd_set'i sabit boyutlu bir tür yapar, FD_SETSIZE 1024 olarak tanımlanır ve FD _ * () makroları bu sınır. 1023'ten büyük dosya tanımlayıcılarını izlemek için, bunun yerine anket (2) kullanın. CentOS 7'de, çekirdek> 1023 dosya tanıtıcısı döndürdüğü için kendi kodumun bir select () 'de başarısız olduğu sorunları zaten gördüm ve şu anda aynı soruna çarpan Twisted gibi kokan bir soruna bakıyorum.
Paul D Smith

4

Şirketimdeki testlerde epoll () ile ilgili bir sorun ortaya çıktı, dolayısıyla select'e kıyasla tek bir maliyet.

Ağdan bir zaman aşımı ile okumaya çalışırken, bir epoll_fd oluşturmak (bir FD_SET yerine) ve fd'yi epoll_fd'ye eklemek, bir FD_SET (basit bir malloc olan) oluşturmaktan çok daha pahalıdır.

Önceki yanıta göre, süreçteki FD sayısı arttıkça, select () maliyeti yükseliyor, ancak bizim testimizde, 10.000'lerde fd değerlerinde bile, select hala kazanan oldu. Bunlar, bir iş parçacığının beklediği yalnızca bir fd'nin olduğu ve yalnızca ağ okuma ve ağ yazmanın, engelleyici bir iş parçacığı modeli kullanılırken zaman aşımına uğramadığı gerçeğinin üstesinden gelmeye çalıştığı durumlardır. Elbette, bloke edici iplik modelleri, bloke edici olmayan reaktör sistemlerine kıyasla düşük performanstır, ancak belirli bir eski kod tabanı ile entegre olmanın gerekli olduğu durumlar vardır.

Bu tür bir kullanım durumu, yüksek performanslı uygulamalarda nadirdir, çünkü bir reaktör modelinin her seferinde yeni bir epoll_fd oluşturması gerekmez. Bir epoll_fd'nin uzun ömürlü olduğu - herhangi bir yüksek performanslı sunucu tasarımında açıkça tercih edilen - model için epoll, her yönden açık bir galiptir.


5
Ancak select()10k + aralığında dosya tanımlayıcı değerleriniz varsa bile kullanamazsınız - sisteminizin yarısını FD_SETSIZE'ı değiştirmek için yeniden derlemediğiniz sürece - bu yüzden bu stratejinin nasıl çalıştığını merak ediyorum. Eğer açıklanan senaryosu için, herhalde bakardık poll()gibi çok daha hangi select()o gibi daha epoll()ama FD_SETSIZE sınırlama kaldırılır -.
Jean-Paul Calderone

10K aralığında dosya tanımlayıcı değerleriniz varsa select () kullanabilirsiniz, çünkü bir FD_SET malloc () yapabilirsiniz. Aslında, FD_SETSIZE derleme zamanı olduğundan ve gerçek fd limiti çalışma zamanında olduğundan, FD_SET'in YALNIZCA güvenli kullanımı, dosya tanımlayıcısının sayısını FD_SET boyutuna göre kontrol eder ve FD_SET ise bir malloc (veya ahlaki eşdeğer) yapar. çok küçük. Bunu bir müşteriyle üretimde gördüğümde şok oldum. 20 yıl boyunca soketleri programladıktan sonra, şimdiye kadar yazdığım kodların tamamı ve web'deki eğitimlerin çoğu güvensiz.
Brian Bulkowski

5
Bildiğim kadarıyla bu hiçbir popüler platformda doğru değil. C kitaplığınız derlendiğinde FD_SETSIZEayarlanan bir derleme zamanı sabitidir . Uygulamanızı oluştururken farklı bir değere tanımlarsanız, uygulamanız ve C kitaplığı aynı fikirde olmayacak ve işler kötü gidecektir. Yeniden tanımlamanın güvenli olduğunu iddia eden referanslarınız varsa, onları görmek isterim. FD_SETSIZE
Jean-Paul Calderone
Sitemizi kullandığınızda şunları okuyup anladığınızı kabul etmiş olursunuz: Çerez Politikası ve Gizlilik Politikası.
Licensed under cc by-sa 3.0 with attribution required.