select चयन से तेज तेज क्यों है?




epoll (2)

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

तो, यांत्रिकी को थोड़ा और समझाने के लिए:

  1. एक epoll फ़ाइल डिस्क्रिप्टर में एक निजी struct eventpoll होता है जो इस एफडी से जुड़े एफडी के ट्रैक को ट्रैक करता है। struct eventpoll में एक प्रतीक्षा कतार भी होती है जो वर्तमान में इस प्रक्रिया पर epoll_wait ing की सभी प्रक्रियाओं का ट्रैक रखती है। struct epoll में सभी फाइल डिस्क्रिप्टरों की एक सूची भी है जो वर्तमान में पढ़ने या लिखने के लिए उपलब्ध हैं।
  2. जब आप epoll_ctl() का उपयोग करते हुए epoll_ctl() एफडी में फ़ाइल डिस्क्रिप्टर जोड़ते हैं, तो struct eventpoll उस एफडी की प्रतीक्षा कतार में struct eventpoll जोड़ता है। यह भी जांचता है कि क्या एफडी वर्तमान में प्रसंस्करण के लिए तैयार है और इसे तैयार सूची में जोड़ता है, यदि ऐसा है।
  3. जब आप epoll_wait का उपयोग करते हुए epoll एफडी पर प्रतीक्षा करते हैं, तो कर्नेल पहले तैयार सूची की जांच करता है, और अगर कोई फ़ाइल डिस्क्रिप्टर पहले से तैयार हो तो तत्काल लौटाता है। यदि नहीं, तो यह खुद को struct eventpoll अंदर एकल प्रतीक्षा कतार में struct eventpoll , और सो जाता है।
  4. जब epoll() एड होने वाली सॉकेट पर कोई ईवेंट होता है, तो यह epoll कॉलबैक को कॉल करता है, जो फ़ाइल डिस्क्रिप्टर को तैयार सूची में जोड़ता है, और उस वेटर्स को भी जागता है जो वर्तमान में उस struct eventpoll पर प्रतीक्षा कर रहे हैं।

जाहिर है, struct eventpoll और विभिन्न सूचियों और प्रतीक्षा कतारों पर बहुत सावधानीपूर्वक लॉकिंग की आवश्यकता है, लेकिन यह एक कार्यान्वयन विस्तार है।

ध्यान देने योग्य महत्वपूर्ण बात यह है कि ऊपर किसी भी बिंदु पर मैंने एक ऐसे चरण का वर्णन नहीं किया जो ब्याज के सभी फाइल डिस्क्रिप्टरों पर लूप करता है। पूरी तरह से घटना-आधारित होने और एफडी और एक तैयार सूची के लंबे समय तक चलने वाले सेट का उपयोग करके, एपोल कभी भी ऑपरेशन के लिए ओ (एन) समय लेने से बच सकता है , जहां एन फाइल डिस्क्रिप्टरों की निगरानी की जा रही है।

मैंने बहुत सारी तुलना देखी है जो कहते हैं कि चयन को एफडी सूची के माध्यम से चलना है, और यह धीमा है। लेकिन एपोल को ऐसा क्यों नहीं करना है?


इसके बारे में बहुत सारी गलत जानकारी है, लेकिन वास्तविक कारण यह है:

एक सामान्य सर्वर 200 कनेक्शन से कह सकता है। यह प्रत्येक कनेक्शन की सेवा करेगा जिसमें डेटा लिखे या पढ़े जाने की आवश्यकता है और फिर इसे तब तक इंतजार करना होगा जब तक कि और अधिक काम न हो जाए। हालांकि, यह इंतजार कर रहा है, अगर उन 200 कनेक्शनों में से किसी एक पर डेटा प्राप्त होता है तो इसे बाधित करने की आवश्यकता होती है।

select साथ, कर्नेल को प्रक्रिया को 200 प्रतीक्षा सूचियों में जोड़ना होगा, प्रत्येक कनेक्शन के लिए एक। ऐसा करने के लिए, प्रतीक्षा सूची में प्रक्रिया को संलग्न करने के लिए इसे "थंक" की आवश्यकता है। जब प्रक्रिया अंत में जागती है, तो इसे सभी 200 प्रतीक्षा सूचियों से हटा दिया जाना चाहिए और उन सभी हिस्सों को मुक्त करने की आवश्यकता है।

इसके विपरीत, epoll साथ, epoll सॉकेट की प्रतीक्षा सूची होती है। प्रक्रिया को केवल एक ही थंक का उपयोग करके केवल एक प्रतीक्षा सूची में रखा जाना चाहिए। जब प्रक्रिया बढ़ जाती है, तो इसे केवल एक प्रतीक्षा सूची से हटा दिया जाना चाहिए और केवल एक थंक को मुक्त करने की आवश्यकता है।

स्पष्ट होने के लिए, epoll साथ, epoll सॉकेट को उन 200 कनेक्शनों में से प्रत्येक से जुड़ा होना चाहिए। लेकिन यह एक बार किया जाता है, प्रत्येक कनेक्शन के लिए, जब इसे पहली जगह स्वीकार किया जाता है। और यह एक बार टूट जाता है, प्रत्येक कनेक्शन के लिए, जब इसे हटा दिया जाता है। इसके विपरीत, प्रत्येक ब्लॉक को select लिए प्रत्येक कॉल को प्रत्येक सॉकेट की निगरानी के लिए प्रत्येक प्रतीक्षा कतार में प्रक्रिया जोड़नी होगी।

विडंबना यह है कि, select साथ, सबसे बड़ी लागत यह जांचने से आती है कि सॉकेट्स में कोई गतिविधि नहीं है या नहीं। epoll साथ, ऐसे सॉकेट की जांच करने की कोई आवश्यकता नहीं है जिनके पास कोई गतिविधि नहीं है क्योंकि यदि उनके पास गतिविधि होती है, तो वे उस गतिविधि के दौरान epoll सॉकेट को सूचित करते थे। एक अर्थ में, प्रत्येक सॉकेट को प्रत्येक बार जब आप कॉल करते हैं तो यह देखने के लिए select करें कि क्या कोई गतिविधि है, जबकि epoll रिग्स है ताकि सॉकेट गतिविधि स्वयं प्रक्रिया को सूचित करे।





epoll