ट्विस्टेड में चुनिंदा / पोल बनाम एपोल रिएक्टर के कैविट्स


95

मैंने जो कुछ भी पढ़ा है और अनुभव किया है (टोरनेडो आधारित ऐप्स) मुझे विश्वास दिलाता है कि ईपॉल सिलेक्ट और पोल आधारित नेटवर्किंग के लिए एक प्राकृतिक प्रतिस्थापन है, विशेष रूप से मुड़ के साथ। जो मुझे पागल बना देता है, एक बेहतर तकनीक या कार्यप्रणाली के लिए इसका बहुत ही दुर्लभ मूल्य के साथ नहीं आना।

एपोल और विकल्पों के बीच एक दो दर्जन तुलनाओं को पढ़ने से पता चलता है कि एपोल स्पष्ट रूप से गति और स्केलेबिलिटी के लिए चैंपियन है, विशेष रूप से यह एक रैखिक फैशन में तराजू है जो शानदार है। उस ने कहा, प्रोसेसर और मेमोरी उपयोग के बारे में क्या, अभी भी शैंपू है?

जवाबों:


190

बहुत कम संख्या में सॉकेट्स के लिए (आपके हार्डवेयर के आधार पर भिन्न होता है, लेकिन निश्चित रूप से हम 10 या उससे कम के ऑर्डर पर कुछ के बारे में बात कर रहे हैं), चयन स्मृति उपयोग और रनटाइम गति में एपोल को हरा सकता है। बेशक, इतनी कम संख्या में सॉकेट्स के लिए, दोनों तंत्र इतने तेज हैं कि आप वास्तव में इस अंतर के बारे में परवाह नहीं करते हैं।

एक स्पष्टीकरण, यद्यपि। दोनों का चयन करें और epoll पैमाने पर रैखिक। हालांकि, एक बड़ा अंतर यह है कि यूजर्स-फेसिंग एपीआई में जटिलताएं होती हैं जो विभिन्न चीजों पर आधारित होती हैं। selectकॉल की लागत मोटे तौर पर उस उच्चतम संख्या फ़ाइल डिस्क्रिप्टर के मान के साथ जाती है जिसे आप इसे पास करते हैं। यदि आप एक एकल fd, 100 पर चयन करते हैं, तो वह लगभग एक ही बार में दोगुना महंगा है, एक ही fd, 50 पर चयन करना। उच्चतम से नीचे अधिक fds जोड़ना बहुत मुक्त नहीं है, इसलिए यह अभ्यास की तुलना में थोड़ा अधिक जटिल है, लेकिन यह अधिकांश कार्यान्वयन के लिए एक अच्छा पहला सन्निकटन है।

एपोल की लागत फ़ाइल डिस्क्रिप्टर की संख्या के करीब है जो वास्तव में उन पर घटनाएं हैं। यदि आप 200 फ़ाइल डिस्क्रिप्टर की निगरानी कर रहे हैं, लेकिन उनमें से केवल 100 में उन पर ईवेंट हैं, तो आप (केवल मोटे तौर पर) केवल उन 100 सक्रिय फ़ाइल डिस्क्रिप्टर के लिए भुगतान कर रहे हैं। यह वह जगह है जहां एपोल अपने प्रमुख लाभों में से एक का चयन करने की पेशकश करता है। यदि आपके पास एक हजार ग्राहक हैं जो ज्यादातर बेकार हैं, तो जब आप चयन करते हैं तो आप अभी भी उनमें से सभी एक हजार का भुगतान कर रहे हैं। हालाँकि, एपोल के साथ, ऐसा लगता है कि आपको केवल कुछ ही मिला है - आप केवल उन लोगों के लिए भुगतान कर रहे हैं जो किसी भी समय सक्रिय हैं।

इसका मतलब यह है कि एपोल अधिकांश वर्कलोड के लिए कम सीपीयू का उपयोग करेगा। जहाँ तक मेमोरी उपयोग की बात है, यह एक टॉस अप का एक सा है। selectअत्यधिक कॉम्पैक्ट तरीके से (एक बिट प्रति फ़ाइल डिस्क्रिप्टर) सभी आवश्यक जानकारी का प्रतिनिधित्व करने का प्रबंधन करता है। और FD_SETSIZE (आमतौर पर 1024) की सीमा पर आप कितने फ़ाइल डिस्क्रिप्टर का उपयोग कर सकते हैं selectइसका मतलब यह है कि आप कभी भी उन तीन fd सेटों के लिए 128 बाइट्स से अधिक खर्च नहीं करेंगे जिनका आप उपयोग कर सकते हैंselect(पढ़ें, लिखना, अपवाद)। उन 384 बाइट्स मैक्स की तुलना में, एपोल एक सुअर की तरह है। प्रत्येक फ़ाइल विवरणक बहु-बाइट संरचना द्वारा दर्शाया गया है। हालाँकि, निरपेक्ष रूप से, यह अभी भी बहुत मेमोरी का उपयोग करने वाला नहीं है। आप कुछ दर्जन किलोबाइट में फ़ाइल डिस्क्रिप्टर की एक बड़ी संख्या का प्रतिनिधित्व कर सकते हैं (लगभग 20k प्रति 1000 फ़ाइल डिस्क्रिप्टर, मुझे लगता है)। और आप इस तथ्य में भी फेंक सकते हैं कि आपको उन सभी बाइट्स के सभी 384 खर्च करने होंगे selectयदि आप केवल एक फाइल डिस्क्रिप्टर की निगरानी करना चाहते हैं, लेकिन इसका मूल्य 1024 है, तो आप जिस एपल के साथ केवल 20 बाइट्स खर्च करेंगे। फिर भी, ये सभी संख्याएँ बहुत छोटी हैं, इसलिए इससे बहुत फ़र्क नहीं पड़ता।

और वहाँ भी है कि epoll के अन्य लाभ, जो शायद आप पहले से ही जानते हैं, कि यह FD_SETSIZE फ़ाइल विवरणकों तक सीमित नहीं है। आप इसका उपयोग कर सकते हैं कि आपके पास जितने फ़ाइल डिस्क्रिप्टर हैं, उतने मॉनिटर करने के लिए। और यदि आपके पास केवल एक फ़ाइल डिस्क्रिप्टर है, लेकिन इसका मान FD_SETSIZE से अधिक है, तो एपोल उसके साथ भी काम करता है, लेकिन selectऐसा नहीं करता है।

बेतरतीब ढंग से, मैंने हाल ही epollमें selectया की तुलना में एक मामूली खामी की खोज की है poll। जबकि इन तीन एपीआई में से कोई भी सामान्य फ़ाइलों (अर्थात, फ़ाइल सिस्टम पर फ़ाइलें) का समर्थन नहीं करता है , selectऔर pollइस तरह के विवरणों को हमेशा पठनीय और हमेशा लिखने योग्य के रूप में रिपोर्टिंग के रूप में समर्थन की कमी पेश करता है। यह उन्हें किसी भी प्रकार के गैर-अवरुद्ध फाइलसिस्टम I / O के लिए अनुपयुक्त बनाता है, एक प्रोग्राम जो फाइल सिस्टम से फाइल डिस्क्रिप्टर का उपयोग करने selectया pollकरने के लिए होता है, कम से कम काम करना जारी रखेगा (या यदि यह विफल हो जाता है, तो यह नहीं होगा क्योंकि की selectया poll), यह यद्यपि शायद सबसे अच्छा प्रदर्शन के साथ नहीं।

दूसरी ओर, इस तरह के एक फ़ाइल डिस्क्रिप्टर की निगरानी करने के लिए कहा जाने पर, epollएक त्रुटि ( EPERM, जाहिर है) के साथ तेजी से विफल हो जाएगा । कड़े शब्दों में, यह शायद ही गलत है। यह स्पष्ट रूप से समर्थन की कमी का संकेत दे रहा है। आम तौर पर मैं स्पष्ट विफलता की स्थिति की सराहना करता हूं, लेकिन यह एक अनैच्छिक है (जहां तक ​​मैं बता सकता हूं) और एक पूरी तरह से टूटे हुए आवेदन में परिणाम देता है, बजाय एक जो केवल संभावित अपमानित प्रदर्शन के साथ संचालित होता है।

व्यवहार में, मैंने देखा है कि यह एकमात्र स्थान है, जब stdio के साथ बातचीत होती है। एक उपयोगकर्ता एक सामान्य फ़ाइल के लिए / से stdout रीडायरेक्ट या कर सकता है। जबकि पहले स्टडिन और स्टडआउट एक पाइप होते थे - जो एपोल द्वारा ठीक-ठीक समर्थित होते थे - फिर यह एक सामान्य फ़ाइल बन जाती है और एपोल ऐप को तोड़ते हुए जोर से विफल हो जाती है।


बहुत अच्छा जवाब। pollपूर्णता के व्यवहार के बारे में स्पष्ट होने पर विचार करें ?
क्वार्क

6
साधारण फ़ाइलों से पढ़ने के व्यवहार पर मेरे दो सेंट: मैं आमतौर पर प्रदर्शन में गिरावट के लिए एकमुश्त विफलता पसंद करता हूं। इसका कारण यह है कि विकास के दौरान इसका पता लगने की बहुत अधिक संभावना है, और इस तरह से ठीक से काम किया जाता है (वास्तविक फ़ाइलों के लिए I / O करने का एक वैकल्पिक तरीका है)। YMMV बेशक: ध्यान देने योग्य मंदी नहीं हो सकती है, जिसमें मामले की विफलता बेहतर नहीं है। लेकिन नाटकीय मंदी जो केवल विशेष मामलों में होती है, विकास के दौरान पकड़ना बहुत कठिन हो सकता है, इसे एक समय बम के रूप में छोड़ दिया जाता है जब वास्तव में तैनात किया जाता है।
क्वार्क

1
बस अपने संपादन को पूरी तरह से पढ़ने के लिए मिला है। एक अर्थ में मैं सहमत हूँ कि इसकी शायद अपने पूर्ववर्तियों की नकल न करने के लिए एपोल के लिए सही नहीं है, लेकिन फिर मैं उस देव की कल्पना कर सकता हूं जिसने EPERM त्रुटि को लागू किया था "सिर्फ इसलिए कि इसकी हमेशा टूटी हुई है, इसे मेरा तोड़ने का अधिकार नहीं है। कुंआ।" और फिर भी एक और काउंटर तर्क, मैं रक्षात्मक प्रोग्रामर हूँ कुछ भी 1 + 1 अतीत संदिग्ध है और मैं अनुग्रह विफलताओं की अनुमति देने के लिए इस तरह से कोड करता हूं। कर्नेल फायर होने के बाद उम्मीद से बाहर रहना अच्छा नहीं है या विचारशील नहीं है।
डेविड

1
@ जीन-पॉल क्या आप केक्यू के बारे में कुछ स्पष्टीकरण जोड़ सकते हैं?
अच्छा व्यक्ति

अलग-अलग प्रदर्शन करना, क्या इसके परिणामस्वरूप कोई समस्या है (से man select) लिनक्स कर्नेल कोई निश्चित सीमा नहीं लगाता है, लेकिन glibc कार्यान्वयन fd_set को एक निश्चित-आकार का प्रकार बनाता है, जिसमें FD_SETSIZE को 1024 के रूप में परिभाषित किया गया है, और FD _ * () मैक्रोज़ के अनुसार काम कर रहा है। वह सीमा। 1023 से अधिक फ़ाइल डिस्क्रिप्टर की निगरानी के लिए, इसके बजाय पोल (2) का उपयोग करें। CentOS 7 पर मैंने पहले से ही उन मुद्दों को देखा है जहां मेरा अपना कोड एक चयन () विफल हो गया है क्योंकि कर्नेल ने फ़ाइल हैंडल> 1023 को लौटा दिया है और मैं वर्तमान में एक समस्या देख रहा हूं जिसमें बदबू आ रही है जैसे कि यह एक ही मुद्दे को मार सकता है।
पॉल डी स्मिथ

4

मेरी कंपनी में परीक्षणों में, एपोल () के साथ एक मुद्दा सामने आया, इस प्रकार चयन की तुलना में एक ही लागत।

जब एक टाइमआउट के साथ नेटवर्क से पढ़ने का प्रयास किया जाता है, तो एक epoll_fd (FD_SET के बजाय) का निर्माण करना, और fd को epoll_fd में जोड़ना, FD_SET (जो एक साधारण मॉलोक है) बनाने की तुलना में बहुत अधिक महंगा है।

पिछले उत्तर के अनुसार, जैसे ही प्रक्रिया में एफडी की संख्या बड़ी हो जाती है, चयन की लागत () अधिक हो जाती है, लेकिन हमारे परीक्षण में, 10,000 के एफडी मूल्यों के साथ, चयन अभी भी एक विजेता था। ये ऐसे मामले हैं जहां केवल एक fd है जो एक थ्रेड पर प्रतीक्षा कर रहा है, और बस इस तथ्य को दूर करने की कोशिश कर रहा है कि नेटवर्क पढ़ा, और नेटवर्क राइट, एक थ्रेडिंग मॉडल का उपयोग करते समय टाइमआउट नहीं करता है। बेशक, ब्लॉकिंग थ्रेड मॉडल गैर-अवरुद्ध रिएक्टर सिस्टम की तुलना में कम प्रदर्शन हैं, लेकिन ऐसे अवसर हैं जहां, एक विशेष विरासत कोड आधार के साथ एकीकृत करने के लिए, यह आवश्यक है।

उच्च प्रदर्शन अनुप्रयोगों में इस तरह का उपयोग मामला दुर्लभ है, क्योंकि एक रिएक्टर मॉडल को हर बार एक नया epoll_fd बनाने की आवश्यकता नहीं होती है। मॉडल के लिए जहां एक epoll_fd लंबे समय तक रहता है --- जो स्पष्ट रूप से किसी भी उच्च प्रदर्शन सर्वर डिजाइन के लिए पसंद किया जाता है --- epoll हर तरह से स्पष्ट विजेता है।


5
लेकिन select()अगर आप 10k + रेंज में फ़ाइल डिस्क्रिप्टर मान रखते हैं, तो भी आप इसका उपयोग नहीं कर सकते - जब तक कि आप FD_SETSIZE को बदलने के लिए अपने सिस्टम को आधा न बदल दें - इसलिए मुझे आश्चर्य है कि यह रणनीति कैसे काम करती है। आपके द्वारा बताए गए परिदृश्य के लिए, मैं शायद इस पर गौर करूंगा कि यह जैसा है, उससे कहीं poll()अधिक select()है epoll()- लेकिन FD_SETSIZO सीमा हटाता है।
जीन-पॉल काल्डेरोन

यदि आप 10K रेंज में फ़ाइल डिस्क्रिप्टर मान रखते हैं, तो आप सेलेक्ट () का उपयोग कर सकते हैं, क्योंकि आप FD_SET को मॉलोक () कर सकते हैं। वास्तव में, चूंकि FD_SETSIZE संकलन समय है और वास्तविक fd सीमा रनटाइम पर है, FD_SET का केवल सुरक्षित उपयोग FD_SET के आकार के विरुद्ध फ़ाइल डिस्क्रिप्टर की संख्या की जांच करता है, और FD_SET होने पर एक मॉलोक (या नैतिक संतुलन) करता है। बहुत छोटा। जब मैंने इसे एक ग्राहक के साथ उत्पादन में देखा तो मैं चौंक गया। 20 साल तक प्रोग्रामिंग सॉकेट के बाद, मैंने कभी भी लिखे गए कोड - और वेब पर अधिकांश ट्यूटोरियल - असुरक्षित हैं।
ब्रायन बुल्कोव्स्की

5
यह सच नहीं है, जहां तक ​​मुझे पता है, किसी भी लोकप्रिय प्लेटफार्मों पर। FD_SETSIZEजब आपका C पुस्तकालय संकलित किया जाता है तो एक संकलन समय स्थिर होता है। यदि आप अपने आवेदन का निर्माण करते समय इसे एक अलग मूल्य पर परिभाषित करते हैं तो आपका आवेदन और सी लाइब्रेरी असहमत होंगे और चीजें खराब हो जाएंगी। यदि आपके पास यह दावा करने के संदर्भ हैं कि यह पुनर्परिभाषित FD_SETSIZEकरना सुरक्षित है, तो मैं उन्हें देखना चाहूंगा।
जीन-पॉल काल्डेरोन
हमारी साइट का प्रयोग करके, आप स्वीकार करते हैं कि आपने हमारी Cookie Policy और निजता नीति को पढ़ और समझा लिया है।
Licensed under cc by-sa 3.0 with attribution required.