FD_SETSIZE против рассчитанного значения
В настройке сервера / клиента у меня есть сервер, соединяющийся с клиентами через несколько (на данный момент 4) различных сокетов. В данный момент я использую select с вычисленным значением set_size, но каков верхний предел, прежде чем вместо него стоит использовать FD_SETSIZE?
Ниже приведены некоторые примеры кода, чтобы проиллюстрировать это. Первый сборочный комплекс:
FD_ZERO(&set);
FD_SET(socket1, &set);
FD_SET(socket2, &set);
FD_SET(socket3, &set);
FD_SET(socket4, &set);
Вот как рассчитывается set_size:
set_size = MAX(socket1, socket2);
set_size = MAX(set_size, socket 3);
set_size = MAX(set_size, socket4);
set_size += 1;
И использование:
while ((cnt = select(set_size, &set, NULL, NULL, &t)) != -1 || errno == EINTR) {
if (cnt > 0)
// Do different stuff depending what socket is active
else
// Keep everything alive and add the sockets to the set again
}
Недавно мне пришлось добавить два новых сокета, и, возможно, мне придется добавить еще в будущем. Когда бы вы использовали FD_SETSIZE в отличие от рассчитанного set_size?
1 ответ
Я никогда не беспокоился об этом, потому что кажется, что это очень мало изменится по сравнению со снижением производительности за использование select()
на первом месте.
Сказав это, я думаю, что всегда стоит рассчитывать правильное значение, потому что это не очень дорого, чтобы рассчитать: если вы сохраняете текущее set_size
в локальной переменной, как вы предлагаете, это O(1) с очень низкой константой каждый раз, когда вы добавляете fd (а именно, сравнение и, возможно, обновление). Удаление fd также является O(1), за исключением того, что оно является последним в списке (в этом случае это O ( set_size
) но обычно лучше). С другой стороны, НЕ рассчитывая set_size
означает, что ядро должно пройти через все FD_SETSIZE
записи каждый раз, когда вы звоните select
, поскольку set_size
вероятно, немного меньше, чем FD_SETSIZE
, это платит, чтобы поставить меньшее значение. Даже если set_size
близко к FD_SETSIZE
, рассчитывая set_size
так дешево, что, вероятно, почти всегда стоит.
Конечно, если вы беспокоитесь о производительности до такой степени, вы должны смотреть на poll()
вместо select()
, Еще лучше, вы должны смотреть на epoll
а также kqueue
за исключением того, что это не переносимо, так как эти функции доступны только в Linux и FreeBSD (включая MacOS) соответственно.