Для дуже невеликої кількості сокетів (звичайно, залежно від вашого обладнання, але ми говоримо про щось приблизно 10 або менше), select може перевершити еполь у використанні пам'яті та швидкості роботи. Звичайно, при такій невеликій кількості розеток обидва механізми настільки швидкі, що вас не хвилює ця різниця у переважній більшості випадків.
Однак одне уточнення. І вибір, і еполь масштабуються лінійно. Однак велика різниця полягає в тому, що API, спрямовані на користувальницький простір, мають складність, яка базується на різних речах. Вартістьselect
дзвінка приблизно відповідає значенню дескриптора файлу з найбільшим номером, який ви передаєте. Якщо вибрати на одному fd, 100, то це приблизно вдвічі дорожче, ніж на одному fd, 50. Додавати більше fds нижче найвищого не зовсім безкоштовно, тому на практиці трохи складніше, ніж це, але це є гарним першим наближенням для більшості реалізацій.
Вартість epoll наближається до кількості дескрипторів файлів, які насправді мають події на них. Якщо ви відстежуєте 200 дескрипторів файлів, але лише 100 із них мають події, то ви (дуже грубо) платите лише за ці 100 активних дескрипторів файлів. Саме тут epoll має тенденцію запропонувати одну із своїх головних переваг перед відбором. Якщо у вас є тисяча клієнтів, які переважно не працюють, тоді, коли ви використовуєте select, ви все одно платите за всі тисячі з них. Однак з epoll це наче у вас лише кілька - ви платите лише за ті, що активні в будь-який момент часу.
Все це означає, що epoll призведе до меншого використання центрального процесора для більшості робочих навантажень. Що стосується використання пам'яті, це трохи підкинути. select
вдається представити всю необхідну інформацію вкрай компактно (один біт на дескриптор файлу). І обмеження FD_SETSIZE (зазвичай 1024) на те, скільки дескрипторів файлів можна використовувати (читання, запис, виняток). Порівняно з тими макс. 384 байтами, epoll - це різновид свині. Кожен дескриптор файлу представлений багатобайтовою структурою. Однак в абсолютному вираженні він все одно не буде використовувати багато пам'яті. Ви можете представити величезну кількість дескрипторів файлів кількома десятками кілобайт (я думаю, приблизно 20 тис. На 1000 дескрипторів файлів). І ви також можете взяти до уваги той факт, що вам доведеться витратити всі 384 цих байтівselect
означає, що ви ніколи не витратите більше 128 байт на кожен з трьох наборів fd, з якими ви можете використовуватиselect
select
якщо ви хочете відстежувати лише один дескриптор файлу, але його значення, як правило, становить 1024, тоді як з epoll ви витратите лише 20 байт. І все-таки всі ці цифри досить малі, тому це не має великої різниці.
І є ще така перевага epoll, про яку ви, мабуть, уже знаєте, що вона не обмежується дескрипторами файлів FD_SETSIZE. Ви можете використовувати його для моніторингу стільки дескрипторів файлів, скільки у вас є. І якщо у вас лише один дескриптор файлу, але його значення більше, ніж FD_SETSIZE, epoll також працює з цим, але select
ні.
Випадково, я також нещодавно виявив один незначний недолік epoll
порівняно з select
або poll
. Хоча жоден із цих трьох API не підтримує звичайні файли (тобто файли у файловій системі), select
і poll
демонструють цю відсутність підтримки, оскільки повідомляють такі дескриптори як завжди читабельні та завжди записні. Це робить їх непридатними для будь-якого значущого типу неблокуючої файлової системи вводу-виводу, програма, яка використовує select
або poll
випадково зустрічає дескриптор файлу з файлової системи, принаймні продовжуватиме працювати (або якщо це не вдасться, це не буде з select
або poll
), хоча йому , можливо , не з кращого продуктивністю.
З іншого боку, epoll
швидко не вдасться з помилкою ( EPERM
мабуть) при запиті відстежувати такий дескриптор файлу. Власне кажучи, це навряд чи неправильно. Це просто явним чином сигналізує про відсутність підтримки. Зазвичай я аплодував би явним умовам відмови, але цей є недокументованим (наскільки я можу зрозуміти) і призводить до повністю зламаної програми, а не до програми, яка просто працює з потенційно погіршеною продуктивністю.
На практиці єдине, що я це бачив, - це взаємодія зі stdio. Користувач може перенаправити stdin або stdout з / на звичайний файл. Тоді як раніше stdin та stdout були б конвеєром - підтримуваним epoll - чудово - тоді він стає звичайним файлом, і epoll голосно виходить з ладу, порушуючи програму.
poll
для повноти?