Распределение сериализованных задач: использовать thread или epoll? - PullRequest
0 голосов
/ 01 июня 2010

Сейчас я нахожусь в такой ситуации, что существует группа предопределенных задач для нескольких клиентов (любой клиент может выполнить любую задачу). Когда клиент подключается к серверу, сервер выбирает задачу из незавершенных задач и отправляет ее клиенту - работа на стороне сервера довольно проста. Клиенту требуется некоторое время, чтобы завершить задачу и отправить результат обратно на сервер.

Поскольку задача должна отправляться только одному клиенту, сервер должен обрабатывать запросы в последовательном порядке. Теперь у меня есть два плана сделать это: создать поток для каждого клиентского соединения, и все потоки по очереди обращаются к пулу задач, или использовать epoll-прослушивание всех соединений и процессов для каждого события клиентов.

Какой из них лучше для работы? Или есть еще идеи? Сервер будет работать на многоядерном компьютере.

Ответы [ 2 ]

1 голос
/ 01 июня 2010

Основной вопрос заключается в том, имеет ли сервер значительную обработку для подготовки задач для клиента. Если нет, то ничего не получится от использования нескольких потоков - наоборот, переключение контекста только добавит накладных расходов. В этом случае лучше всего использовать epoll (скорее всего, через какую-то существующую библиотеку, в зависимости от используемого вами языка программирования).

Если означает значительную обработку на стороне сервера, это может компенсировать неэффективность переключения контекста и повысить производительность за счет получения параллелизма от нескольких ядер. Единственный способ точно узнать, каким будет наилучшее решение, - это создать прототипы и профилирование.

Клиенты работают на той же машине, что и сервер? Если они есть, вы сможете легко использовать несколько ядер.

0 голосов
/ 01 июня 2010

Вы можете сделать оба. Вы можете иметь несколько потоков, запускающих epoll() на одном и том же наборе fd, и операционная система будет запускать потоки по мере необходимости. Это также очень легко сделать, особенно если вам не нужно делиться: просто fork() пятьдесят раз или около того, и Linux будет переключать контекст при необходимости и epoll, когда нет. Когда я делаю это, я просто делаю что-то вроде этого:

{char*s=getenv("THREADS");int n=atoi(s?s:"0"),i;
 for(i=0;i<n;i++)if(fork()==0)break;}

Если вам нужно поделиться, то вам понадобится блокировка. Это может усложнить ситуацию, и такие проблемы программирования в общем смысле трудно решить. По моему опыту, за исключением некоторых очень простых баз данных, обычно проще либо отказаться от потоков, либо реорганизовать программу, чтобы не требовать блокировки общих структур.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...