Книга: Разработка приложений в среде Linux. Второе издание
13.1.6 Сравнение poll() и epoll
13.1.6 Сравнение poll()
и epoll
Методы poll()
и epoll
существенно отличаются; poll()
хорошо стандартизован, но плохо масштабируется, в то время как epoll
существует только в Linux, но очень хорошо масштабируется. Приложения, наблюдающие за небольшим количеством файловых дескрипторов и переносимости величин, должны использовать poll()
, но любому приложению, которому необходимо контролировать большое количество дескрипторов, лучше применять epoll
, даже если ему нужно поддерживать poll()
для других платформ.
Отличия в производительности двух методов поразительны. Чтобы продемонстрировать, насколько лучше масштабируется epoll
, в коде poll-vs-epoll.с
измеряется количество системных вызовов poll()
и epoll_wait()
, которые можно создать за одну секунду для наборов файловых дескрипторов разных размеров (количество файловых дескрипторов для помещения в набор задается в командной строке). Каждый файловый дескриптор ссылается на считывающую часть канала, и они создаются с помощью dup2()
.
В табл. 13.1 суммируются результаты запуска poll-vs-epoll.с
для установленных размеров диапазоном от одного до 100 000 файловых дескрипторов[82]. В то время как количество системных вызовов в секунду резко падает для poll()
, оно остается почти постоянным для epoll
[83]. Как поясняет эта таблица, epoll
добавляет в систему намного меньше нагрузки, чем poll()
, и в результате гораздо лучше масштабируется.
Таблица 13.1. Результаты сравнения poll()
и epoll()
Файловые дескрипторы | poll() |
epoll() |
---|---|---|
1 |
310063 |
714848 |
10 |
140842 |
726108 |
100 |
25866 |
726659 |
1000 |
3343 |
729072 |
5000 |
612 |
718424 |
10000 |
300 |
730483 |
25000 |
108 |
717097 |
50000 |
38 |
729746 |
100000 |
18 |
712301 |
1: /* poll-vs-epoll.с */
2:
3: #include <errno.h>
4: #include <fcntl.h>
5: #include <stdio.h>
6: #include <sys/epoll.h>
7: #include <sys/poll.h>
8: #include <sys/signal.h>
9: #include <unistd.h>
10: #include <sys/resource.h>
11: #include <string.h>
12: #include <stdlib.h>
13:
14: #include <sys/select.h>
15:
16: int gotAlarm;
17:
18: void catch(int sig) {
19: gotAlarm = 1;
20: }
21:
22: #define OFFSET 10
23:
24: int main(int argc, const char ** argv) {
25: int pipeFds[2];
26: int count;
27: int numFds;
28: struct pollfd * pollFds;
29: struct epoll_event event;
30: int epfd;
31: int i;
32: struct rlimit lim;
33: char * end;
34:
35: if (!argv[1]) {
36: fprintf(stderr, "ожидалось числоn");
37: return 1;
38: }
39:
40: numFds = strtol(argv[1], &end, 0);
41: if (*end) {
42: fprintf(stderr, "ожидалось числоn");
43: return 1;
44: }
45:
46: printf("Запуск теста для %d файловых дескрипторов.n", numFds);
47:
48: lim.rlim_cur = numFds + OFFSET;
49: lim.rlim_max = numFds + OFFSET;
50: if (setrlimit(RLIMIT_NOFILE, &lim)) {
51: perror("setrlimit");
52: exit(1);
53: }
54:
55: pipe(pipeFds);
56:
57: pollFds = malloc(sizeof (*pollFds) * numFds);
58:
59: epfd = epoll_create(numFds);
60: event.events = EPOLLIN;
61:
62: for (i = OFFSET; i < OFFSET + numFds; i++) {
63: if (dup2(pipeFds[0], i) != i) {
64: printf("сбой в %d: %sn", i, strerror(errno));
65: exit(1);
66: }
67:
68: pollFds[i - OFFSET].fd = i;
69: pollFds[i - OFFSET].events = POLLIN;
70:
71: event.data.fd = i;
72: epoll_ctl(epfd, EPOLL_CTL_ADD, i, &event);
73: }
74:
75: /* с помощью signal выяснить, когда время истекло */
76: signal(SIGALRM, catch);
77:
78: count = 0;
79: gotAlarm = 0;
80: alarm(1);
81: while (!gotAlarm) {
82: poll(pollFds, numFds, 0);
83: count++;
84: }
85:
86: printf("Вызовов poll() в секунду: %dn", count);
87:
88: alarm(1);
89:
90: count = 0;
91: gotAlarm = 0;
92: alarm(1);
93: while (!gotAlarm) {
94: epoll_wait(epfd, &event, 1, 0);
95: count++;
96: }
97:
98: printf("Вызовов epoll() в секунду: %dn", count);
99:
100: return 0;
101: }
- 13.1.2. Мультиплексирование с помощью poll()
- 13.1.4. Сравнение poll() и select()
- 8.1.4. Сравнение массивов
- 4.2 Сравнение SAN и NAS
- Сравнение C# и C++
- 3.2. Сравнение операционных систем
- Сравнение ценностных профилей партнеров
- Большое сравнение: Fedora, openSUSE, Ubuntu
- 12.2.3. Сравнение блоков памяти: memcmp()
- 13.2.3. Сравнение строк: strcoll() и strxfrm()
- Сравнение времени выполнения различных версий функции str_cli
- 13.1.5. Мультиплексирование с помощью epoll