ข้อควรระวังในการเลือก / สำรวจเทียบกับเครื่องปฏิกรณ์ epoll ใน Twisted


95

ทุกสิ่งที่ฉันอ่านและได้สัมผัส (แอพที่ใช้ Tornado) ทำให้ฉันเชื่อว่า ePoll เป็นสิ่งทดแทนตามธรรมชาติสำหรับเครือข่ายแบบเลือกและแบบสำรวจโดยเฉพาะอย่างยิ่งกับ Twisted ซึ่งทำให้ฉันหวาดระแวงมันค่อนข้างหายากสำหรับเทคนิคหรือวิธีการที่ดีกว่าที่จะไม่มาพร้อมกับราคา

การอ่านการเปรียบเทียบสองสามโหลระหว่าง epoll และทางเลือกแสดงให้เห็นว่า epoll เป็นแชมป์ในด้านความเร็วและความสามารถในการปรับขนาดได้อย่างชัดเจนโดยเฉพาะอย่างยิ่งการปรับขนาดเป็นเส้นตรงซึ่งยอดเยี่ยมมาก ที่กล่าวว่าเกี่ยวกับการใช้โปรเซสเซอร์และหน่วยความจำ epoll ยังคงเป็นแชมป์หรือไม่?

คำตอบ:


191

สำหรับซ็อกเก็ตจำนวนน้อยมาก (แน่นอนแตกต่างกันไปขึ้นอยู่กับฮาร์ดแวร์ของคุณ แต่เรากำลังพูดถึงบางอย่างตามลำดับ 10 หรือน้อยกว่า) เลือกสามารถเอาชนะ epoll ในการใช้หน่วยความจำและความเร็วรันไทม์ แน่นอนว่าสำหรับซ็อกเก็ตจำนวนน้อยกลไกทั้งสองนั้นเร็วมากจนคุณไม่สนใจเกี่ยวกับความแตกต่างนี้ในกรณีส่วนใหญ่

แม้ว่าการชี้แจงอย่างใดอย่างหนึ่ง ทั้ง select และ epoll scale linearly แม้ว่าความแตกต่างอย่างมากก็คือ APIs ที่หันหน้าเข้าหาผู้ใช้มีความซับซ้อนที่ขึ้นอยู่กับสิ่งต่างๆ ค่าใช้จ่ายของการselectโทรจะประมาณตามค่าของตัวอธิบายไฟล์ที่มีหมายเลขสูงสุดที่คุณส่งผ่าน หากคุณเลือก fd เดียว 100 ก็จะแพงกว่าการเลือก fd ตัวเดียว 50 ประมาณสองเท่าการเพิ่ม fds ให้ต่ำกว่าค่าสูงสุดนั้นไม่เสียค่าใช้จ่ายดังนั้นในทางปฏิบัติจึงค่อนข้างซับซ้อนกว่านี้เล็กน้อย เป็นค่าประมาณแรกที่ดีสำหรับการใช้งานส่วนใหญ่

ค่าใช้จ่ายของ epoll ใกล้เคียงกับจำนวนตัวอธิบายไฟล์ที่มีเหตุการณ์อยู่ หากคุณกำลังตรวจสอบตัวอธิบายไฟล์ 200 ไฟล์ แต่มีเพียง 100 ตัวเท่านั้นที่มีเหตุการณ์ในนั้นแสดงว่าคุณ (โดยประมาณมาก) จ่ายเงินสำหรับตัวอธิบายไฟล์ที่ใช้งาน 100 ไฟล์เท่านั้น นี่คือจุดที่ epoll มีแนวโน้มที่จะนำเสนอข้อได้เปรียบที่สำคัญอย่างหนึ่งมากกว่าการเลือก หากคุณมีลูกค้านับพันรายที่ส่วนใหญ่ไม่ได้ใช้งานเมื่อคุณใช้ select คุณจะยังคงจ่ายเงินให้กับลูกค้าทั้งหมดหนึ่งพันราย อย่างไรก็ตามด้วย epoll ก็เหมือนกับว่าคุณมีเพียงไม่กี่ชิ้นเท่านั้นคุณจะจ่ายเฉพาะรายการที่มีการใช้งานในช่วงเวลาใดเวลาหนึ่ง

ทั้งหมดนี้หมายความว่า epoll จะนำไปสู่การใช้งาน CPU น้อยลงสำหรับภาระงานส่วนใหญ่ เท่าที่การใช้งานหน่วยความจำดำเนินไปมันก็ค่อนข้างแย่ selectจัดการเพื่อแสดงข้อมูลที่จำเป็นทั้งหมดในรูปแบบที่กะทัดรัดมาก (หนึ่งบิตต่อตัวอธิบายไฟล์) และข้อ จำกัด FD_SETSIZE (โดยทั่วไปคือ 1024) เกี่ยวกับจำนวนตัวอธิบายไฟล์ที่คุณสามารถใช้โดยselectหมายความว่าคุณจะไม่ใช้จ่ายเกิน 128 ไบต์สำหรับชุด fd ทั้งสามชุดที่คุณสามารถใช้ได้select(อ่านเขียนข้อยกเว้น) เมื่อเทียบกับสูงสุด 384 ไบต์แล้ว epoll ก็เหมือนกับหมู ตัวอธิบายไฟล์แต่ละตัวจะแสดงด้วยโครงสร้างแบบหลายไบต์ อย่างไรก็ตามในแง่ที่แน่นอนมันจะยังไม่ใช้หน่วยความจำมากนัก คุณสามารถแสดงตัวอธิบายไฟล์จำนวนมากได้ในไม่กี่สิบกิโลไบต์ (ฉันคิดว่าประมาณ 20k ต่อ 1,000 ตัวอธิบายไฟล์) และคุณยังสามารถโยนความจริงที่ว่าคุณต้องใช้จ่ายทั้งหมด 384 ไบต์selectหากคุณต้องการตรวจสอบตัวอธิบายไฟล์เพียงไฟล์เดียว แต่ค่าของมันเป็น 1024 ส่วน epoll คุณจะใช้จ่ายเพียง 20 ไบต์เท่านั้น ถึงกระนั้นตัวเลขทั้งหมดนี้ก็ค่อนข้างเล็กจึงไม่ได้สร้างความแตกต่างมากนัก

นอกจากนี้ยังมีประโยชน์อื่น ๆ ของ epoll ซึ่งบางทีคุณอาจทราบอยู่แล้วว่าไม่ จำกัด เฉพาะคำอธิบายไฟล์ FD_SETSIZE คุณสามารถใช้เพื่อตรวจสอบตัวอธิบายไฟล์ได้มากเท่าที่คุณมี และหากคุณมีตัวอธิบายไฟล์เพียงตัวเดียว แต่ค่าของไฟล์นั้นมากกว่า FD_SETSIZE epoll ก็ใช้ได้เช่นกัน แต่selectไม่มี

สุ่มฉันยังเพิ่งค้นพบหนึ่งอุปสรรคเล็กน้อยepollเมื่อเทียบกับหรือselect pollแม้ว่า API ทั้งสามตัวนี้จะไม่รองรับไฟล์ปกติ (เช่นไฟล์ในระบบไฟล์) selectและpollนำเสนอการขาดการสนับสนุนนี้เช่นการรายงานตัวอธิบายที่อ่านได้และเขียนได้เสมอ สิ่งนี้ทำให้ไม่เหมาะสำหรับ I / O ระบบไฟล์ที่ไม่มีการปิดกั้นที่มีความหมายใด ๆ โปรแกรมที่ใช้selectหรือpollและบังเอิญพบตัวอธิบายไฟล์จากระบบไฟล์อย่างน้อยก็จะยังคงทำงานต่อไป (หรือหากล้มเหลวก็จะไม่เป็นเพราะ ของselectหรือpoll) แม้ว่าอาจจะไม่ได้มีประสิทธิภาพที่ดีที่สุด

ในทางกลับกันepollจะล้มเหลวอย่างรวดเร็วโดยมีข้อผิดพลาด ( EPERMเห็นได้ชัด) เมื่อถูกขอให้ตรวจสอบตัวอธิบายไฟล์ดังกล่าว พูดอย่างเคร่งครัดนี่แทบจะไม่ถูกต้อง เป็นเพียงการส่งสัญญาณว่าไม่มีการสนับสนุนอย่างชัดเจน โดยปกติฉันจะปรบมือให้กับเงื่อนไขความล้มเหลวอย่างชัดเจน แต่สิ่งนี้ไม่มีเอกสาร (เท่าที่ฉันสามารถบอกได้) และส่งผลให้แอปพลิเคชันเสียโดยสิ้นเชิงแทนที่จะเป็นแอปพลิเคชันที่ทำงานด้วยประสิทธิภาพที่ลดลงเท่านั้น

ในทางปฏิบัติสถานที่เดียวที่ฉันเห็นสิ่งนี้เกิดขึ้นคือเมื่อโต้ตอบกับ stdio ผู้ใช้อาจเปลี่ยนเส้นทาง stdin หรือ stdout จาก / ไปยังไฟล์ปกติ ในขณะที่ก่อนหน้านี้ stdin และ stdout จะเป็นไปป์ - รองรับโดย epoll ได้ดี - จากนั้นก็กลายเป็นไฟล์ปกติและ epoll ก็ล้มเหลวเสียงดังทำให้แอปพลิเคชันเสียหาย


คำตอบที่ดีมาก พิจารณาให้ชัดเจนเกี่ยวกับพฤติกรรมของpollเพื่อความสมบูรณ์?
ควาร์ก

6
สองเซ็นต์ของฉันเกี่ยวกับพฤติกรรมการอ่านจากไฟล์ธรรมดา: โดยทั่วไปฉันชอบความล้มเหลวในการลดประสิทธิภาพโดยสิ้นเชิง เหตุผลก็คือมีแนวโน้มที่จะตรวจพบได้มากกว่าในระหว่างการพัฒนาและทำงานได้อย่างถูกต้อง (พูดโดยมีวิธีอื่นในการทำ I / O สำหรับไฟล์จริง) แน่นอน YMMV: อาจไม่มีการชะลอตัวที่เห็นได้ชัดซึ่งในกรณีนี้ความล้มเหลวจะไม่ดีขึ้น แต่การชะลอตัวอย่างมากที่เกิดขึ้นเฉพาะในกรณีพิเศษนั้นยากที่จะจับได้ในระหว่างการพัฒนาปล่อยทิ้งไว้เป็นระเบิดเวลาเมื่อนำไปใช้งานจริง
ควาร์ก

1
เพิ่งจะอ่านการแก้ไขของคุณอย่างสมบูรณ์ ในแง่หนึ่งฉันยอมรับว่ามันอาจไม่ถูกต้องสำหรับ epoll ที่จะไม่เลียนแบบรุ่นก่อน แต่อีกครั้งฉันสามารถจินตนาการได้ว่า dev ที่ใช้ข้อผิดพลาด EPERM คิดว่า "เพียงเพราะมันพังตลอดเวลาไม่เหมาะสมที่จะทำลายของฉันในฐานะ ดี." และอีกข้อโต้แย้งหนึ่งฉันเป็นโปรแกรมเมอร์ป้องกันอะไรก็ตามที่ผ่านมา 1 + 1 เป็นผู้ต้องสงสัยและฉันเขียนโค้ดเพื่อให้เกิดความล้มเหลวอย่างสง่างาม การที่เคอร์เนลทำงานผิดพลาดจากความคาดหมายไม่ใช่เรื่องดีหรือน่าพิจารณา
เดวิด

1
@ Jean-Paul คุณช่วยเพิ่มคำอธิบายเกี่ยวกับ kqueue ด้วยได้ไหม?
คนดี

นอกเหนือจากประสิทธิภาพแล้วมีปัญหาที่เกิดจากสิ่งนี้หรือไม่ (จากman select) เคอร์เนลของลินุกซ์ไม่ได้กำหนดขีด จำกัด ตายตัว แต่การใช้งาน glibc ทำให้ fd_set เป็นประเภทขนาดคงที่โดย FD_SETSIZE กำหนดเป็น 1024 และมาโคร FD _ * () ทำงานตาม ขีด จำกัด นั้น หากต้องการตรวจสอบตัวอธิบายไฟล์ที่มากกว่า 1023 ให้ใช้แบบสำรวจ (2) แทน ใน CentOS 7 ฉันได้เห็นปัญหาที่รหัสของตัวเองล้มเหลวในการเลือก () เนื่องจากเคอร์เนลส่งคืนที่จับไฟล์> 1023 และฉันกำลังดูปัญหาที่มีกลิ่นเหมือนว่ามันอาจจะบิดตีปัญหาเดียวกัน
Paul D Smith

4

ในการทดสอบที่ บริษัท ของฉันปัญหาหนึ่งเกี่ยวกับ epoll () เกิดขึ้นดังนั้นจึงมีค่าใช้จ่ายเพียงครั้งเดียวเมื่อเทียบกับการเลือก

เมื่อพยายามอ่านจากเครือข่ายด้วยการหมดเวลาการสร้าง epoll_fd (แทนที่จะเป็น FD_SET) และการเพิ่ม fd ลงใน epoll_fd นั้นมีราคาแพงกว่าการสร้าง FD_SET (ซึ่งเป็น malloc ธรรมดามาก)

ตามคำตอบก่อนหน้านี้เนื่องจากจำนวน FD ในกระบวนการมีมากขึ้นค่าใช้จ่ายในการเลือก () จึงสูงขึ้น แต่ในการทดสอบของเราแม้จะมีค่า fd ใน 10,000 ตัวเลือกก็ยังคงเป็นผู้ชนะ นี่เป็นกรณีที่มี fd เพียงตัวเดียวที่เธรดกำลังรออยู่และเพียงแค่พยายามเอาชนะความจริงที่ว่าเครือข่ายอ่านและเขียนเครือข่ายไม่หมดเวลาเมื่อใช้โมเดลเธรดการบล็อก แน่นอนว่าโมเดลเธรดการบล็อกนั้นมีประสิทธิภาพต่ำเมื่อเทียบกับระบบเครื่องปฏิกรณ์แบบไม่ปิดกั้น แต่มีบางครั้งที่จำเป็นต้องใช้ร่วมกับฐานรหัสเดิมโดยเฉพาะ

กรณีการใช้งานแบบนี้หายากในแอปพลิเคชันประสิทธิภาพสูงเนื่องจากแบบจำลองเครื่องปฏิกรณ์ไม่จำเป็นต้องสร้าง epoll_fd ใหม่ทุกครั้ง สำหรับรุ่นที่ epoll_fd มีอายุการใช้งานยาวนาน - ซึ่งเป็นที่ต้องการอย่างชัดเจนสำหรับการออกแบบเซิร์ฟเวอร์ประสิทธิภาพสูงใด ๆ - epoll เป็นผู้ชนะที่ชัดเจนในทุก ๆ ด้าน


5
แต่คุณไม่สามารถใช้งานได้select()หากคุณมีค่าตัวอธิบายไฟล์ในช่วง 10k + เว้นแต่คุณจะคอมไพล์ระบบของคุณใหม่ครึ่งหนึ่งเพื่อเปลี่ยน FD_SETSIZE - ดังนั้นฉันจึงสงสัยว่ากลยุทธ์นี้ทำงานอย่างไร สำหรับสถานการณ์ที่คุณอธิบายไว้ฉันอาจจะดูpoll()ว่าเป็นแบบไหนselect()มากกว่าที่เป็นอยู่epoll()- แต่ลบข้อ จำกัด FD_SETSIZE ออก
Jean-Paul Calderone

คุณสามารถใช้ select () หากคุณมีค่าตัวอธิบายไฟล์ในช่วง 10K เนื่องจากคุณสามารถ malloc () เป็น FD_SET ในความเป็นจริงเนื่องจาก FD_SETSIZE เป็นเวลาคอมไพล์และขีด จำกัด fd ที่แท้จริงอยู่ที่รันไทม์การใช้ FD_SET อย่างปลอดภัยเท่านั้นจะตรวจสอบจำนวนตัวอธิบายไฟล์เทียบกับขนาดของ FD_SET และทำ malloc (หรือเทียบเท่าทางศีลธรรม) หาก FD_SET เป็น เล็กเกินไป. ฉันตกใจมากเมื่อเห็นสิ่งนี้ในการผลิตกับลูกค้า หลังจากการเขียนโปรแกรมซ็อกเก็ตเป็นเวลา 20 ปีโค้ดทั้งหมดที่ฉันเคยเขียนและบทช่วยสอนส่วนใหญ่บนเว็บนั้นไม่ปลอดภัย
Brian Bulkowski

5
นี่ไม่เป็นความจริงเท่าที่ฉันรู้บนแพลตฟอร์มยอดนิยมใด ๆ FD_SETSIZEเป็นชุดเวลาคงรวบรวมเมื่อคุณCห้องสมุดจะรวบรวม หากคุณกำหนดให้เป็นค่าอื่นเมื่อคุณสร้างแอปพลิเคชันของคุณแอปพลิเคชันและไลบรารี C ของคุณจะไม่เห็นด้วยและสิ่งต่างๆจะไม่ดี หากคุณมีข้อมูลอ้างอิงที่อ้างว่าสามารถกำหนดนิยามใหม่ได้อย่างปลอดภัยFD_SETSIZEฉันสนใจที่จะดู
Jean-Paul Calderone
โดยการใช้ไซต์ของเรา หมายความว่าคุณได้อ่านและทำความเข้าใจนโยบายคุกกี้และนโยบายความเป็นส่วนตัวของเราแล้ว
Licensed under cc by-sa 3.0 with attribution required.