การสำรวจความคิดเห็นกับการเลือกแตกต่างกันอย่างไร


คำตอบ:


90

ฉันคิดว่านี่ตอบคำถามของคุณ:

จาก Richard Stevens (rstevens@noao.edu):

ความแตกต่างพื้นฐานคือ fd_set ของ select () เป็นรูปแบบบิตดังนั้นจึงมีขนาดคงที่ เป็นไปได้สำหรับเคอร์เนลที่จะไม่ จำกัด ขนาดนี้เมื่อเคอร์เนลถูกคอมไพล์ทำให้แอปพลิเคชันสามารถกำหนด FD_SETSIZE ให้กับสิ่งที่มันต้องการ (เป็นความคิดเห็นในส่วนหัวของระบบบ่งบอกถึงวันนี้) แต่ใช้งานได้มากกว่า เคอร์เนล 4.4BSD และฟังก์ชันไลบรารี Solaris ทั้งคู่มีข้อ จำกัด นี้ แต่ฉันเห็นว่าตอนนี้ BSD / OS 2.1 ได้รับการเข้ารหัสเพื่อหลีกเลี่ยงข้อ จำกัด นี้ดังนั้นจึงเป็นไปได้เพียงเรื่องเล็ก ๆ ของการเขียนโปรแกรม :-) ใครบางคนควรยื่นรายงานข้อผิดพลาดของ Solaris เกี่ยวกับเรื่องนี้และดูว่ามันได้รับการแก้ไขแล้วหรือไม่

ด้วยโพล () ผู้ใช้จะต้องจัดสรรอาเรย์ของโครงสร้างโพลฟด์และส่งจำนวนรายการในอาเรย์นี้ดังนั้นจึงไม่มีข้อ จำกัด ขั้นพื้นฐาน ในฐานะที่เป็นโน้ตแคสเปอร์ระบบน้อยกว่าจึงมีการสำรวจความคิดเห็น () มากกว่าตัวเลือกดังนั้นระบบหลังจึงพกพาได้มากกว่า นอกจากนี้ด้วยการใช้งานดั้งเดิม (SVR3) คุณไม่สามารถตั้งค่า descriptor เป็น -1 เพื่อบอกเคอร์เนลให้ละเว้นรายการในโครงสร้างของ pollfd ซึ่งทำให้ยากต่อการลบรายการออกจากอาร์เรย์ SVR4 มาถึงสิ่งนี้ โดยส่วนตัวฉันมักจะใช้ select () และไม่ค่อยมีการสำรวจความคิดเห็น () เพราะฉันพอร์ตโค้ดของฉันไปยังสภาพแวดล้อม BSD ด้วย บางคนสามารถเขียนการดำเนินการสำรวจความคิดเห็น () ที่ใช้ select () สำหรับสภาพแวดล้อมเหล่านี้ แต่ฉันไม่เคยเห็นมาก่อน ทั้ง select () และแบบสำรวจ () กำลังได้มาตรฐานโดย POSIX 1003.1g

อัปเดตตุลาคม 2017:

อีเมลที่อ้างถึงข้างต้นมีอายุอย่างน้อยเท่ากับปี 2001 poll()คำสั่งอยู่ในขณะนี้ (2017) ได้รับการสนับสนุนในทุกระบบปฏิบัติการที่ทันสมัย - รวมทั้ง BSD ในความเป็นจริงบางคนเชื่อว่าควรจะเลิกใช้select() ความคิดเห็นเกี่ยวกับปัญหาด้านการพกพาpoll()ไม่ได้กังวลกับระบบที่ทันสมัยอีกต่อไป นอกจากนี้epoll()ยังได้รับการพัฒนา (คุณสามารถอ่าน man page ) และยังคงได้รับความนิยมเพิ่มขึ้นอย่างต่อเนื่อง

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


15
สตีเวนส์ตอบเมื่อใด ความคิดเห็นเกี่ยวกับการสำรวจความคิดเห็น () ยังไม่พร้อมใช้งานบน BSD ยังคงใช้อยู่ MacOS X (ซึ่งส่วนหนึ่งเป็นไปตาม BSD) มีแบบสำรวจ () และมาตรฐาน POSIX (POSIX 2008) จำเป็นต้องใช้
Jonathan Leffler

12
สตีเว่นรวยเสียชีวิตในเดือนกันยายน 2542 ดังนั้นคำตอบต้องเก่ากว่านั้น เขากล่าวถึงการเห็นการเปลี่ยนแปลงใหม่ใน BSD / OS 2.1 ซึ่งเปิดตัวในเดือนมกราคม 2539 ดังนั้นอาจเป็นไปได้
alanc

2
ฉันไม่เชื่อหรอก โพสต์คำตอบ 5 ปีที่ผ่านมาฉันสะดุดมันทิ้งไว้เปิดในเบราว์เซอร์ ในวันถัดไปผู้เขียนจะแก้ไขและปรับปรุงคำตอบ ดังนั้นแจ้งให้ฉันทราบด้วยการอัปเดตในหน้าเว็บโดยใช้ AJAX / websocket นี่คือเหตุผลว่าทำไมจึงดีมาก
Steven Lu

9
@StevenLu ใช่ แต่น่าเสียดายที่ไม่มีคำว่า AJAX / websocket ใช้selectหรือpoll:(
Christopher Schultz

> บางคนสามารถเขียนการนำโพล () ไปใช้ซึ่งเลือก () สำหรับสภาพแวดล้อมเหล่านี้ แต่ฉันไม่เคยเห็นเลย Java ทำเช่นนั้น ;-)
Sergey Mashkov

229

การselect()เรียกนั้นให้คุณสร้าง bitmasks สามตัวเพื่อทำเครื่องหมายซ็อกเก็ตและตัวอธิบายไฟล์ที่คุณต้องการดูสำหรับการอ่านการเขียนและข้อผิดพลาดจากนั้นระบบปฏิบัติการจะทำเครื่องหมายว่าอันที่จริงแล้วมีกิจกรรมประเภทใด poll()คุณได้สร้างรายการ descriptor IDs และระบบปฏิบัติการทำเครื่องหมายแต่ละรายการด้วยประเภทของเหตุการณ์ที่เกิดขึ้น

select()วิธีการค่อนข้าง clunky และไม่มีประสิทธิภาพ

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

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

  3. เนื่องจากระบบปฏิบัติการส่งสัญญาณคุณเกี่ยวกับกิจกรรมโดยการเขียน bitmasks ใหม่อีกครั้งพวกมันจะถูกทำลายและไม่ถูกทำเครื่องหมายด้วยรายการตัวอธิบายไฟล์ที่คุณต้องการฟังอีกต่อไป คุณต้องสร้าง bitmask ทั้งหมดใหม่จากรายการอื่นที่คุณเก็บไว้ในหน่วยความจำหรือคุณต้องเก็บสำเนาซ้ำของแต่ละ bitmask และmemcpy()บล็อกของข้อมูลที่อยู่ด้านบนของ bitmasks ที่ถูกทำลายหลังจากการselect()โทรแต่ละครั้ง

ดังนั้นpoll()วิธีการใช้งานจะดีกว่ามากเพราะคุณสามารถใช้โครงสร้างข้อมูลเดียวกันซ้ำได้

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

http://scotdoyle.com/python-epoll-howto.html

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

http://lse.sourceforge.net/epoll/index.html


อัปเดต:นี่คือคำถาม Stack Overflow อีกคำตอบที่ให้รายละเอียดเพิ่มเติมเกี่ยวกับความแตกต่าง:

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


1
และ +1 สำหรับการเชื่อมโยงกับตัวอย่างของการใช้ epoll ในไพ ธ อน - ดูเหมือนว่ามีตัวอย่างที่น่าสนใจอยู่ที่นั่นและฉันจะต้องลองดู ...
Allen George

+1 เพื่ออธิบายคำตอบ; -1 สำหรับการกล่าวถึง epoll แต่ไม่ใช่ kqueue
บุคคลที่ดี

คำตอบนี้ทำให้เสียงเหมือน epoll เป็นเสมอดีกว่า
user3467349

0

ทั้งสองอย่างนั้นช้าและส่วนใหญ่เหมือนกันแต่มีขนาดและคุณสมบัติแตกต่างกัน!

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

โดยการใช้ไซต์ของเรา หมายความว่าคุณได้อ่านและทำความเข้าใจนโยบายคุกกี้และนโยบายความเป็นส่วนตัวของเราแล้ว
Licensed under cc by-sa 3.0 with attribution required.