Самый быстрый метод сокетов для большого количества данных между большим количеством файлов - PullRequest
4 голосов
/ 01 декабря 2009

Я создаю приложение для сокетов, которое должно перетасовывать множество файлов малого / среднего размера, например, файлы размером 5-100 КБ, для множества разных клиентов (вроде веб-сервера, но все же не совсем).

Должен ли я просто использовать стандартный опрос / epoll (linux) или асинхронные сокеты в winsock (win32), или есть какие-либо методы с еще большей производительностью (например, перекрытие ввода-вывода на win32)?

И Linux, и Windows являются возможными платформами!

Ответы [ 6 ]

3 голосов
/ 01 декабря 2009

В Linux демультиплексирование нескольких сокетов с использованием epoll - это самый быстрый из возможных способов параллельного ввода-вывода по TCP.

Но я также упомяну, что в интересах переносимости (и, поскольку вы, похоже, интересуетесь либо Linux, либо Windows), вам следует заглянуть в Boost.Asio. Он имеет переносимый API, но использует epoll в Linux и перекрывающийся ввод / вывод в Windows, поэтому вы можете создавать высокоэффективные и портативные сетевые приложения.

Кроме того, поскольку вы работаете с файлами, вы должны также реализовать двойную буферизацию при выполнении операций ввода-вывода для максимальной производительности. Другими словами, вы отправляете / извлекаете каждый файл, используя два буфера. Например, на отправляющей стороне вы читаете с диска в один буфер, а затем отправляете этот буфер по сети, в то время как другой поток считывает следующий блок данных с диска во второй буфер. Таким образом, вы перекрываете дисковый ввод-вывод с сетевым вводом-выводом.

2 голосов
/ 02 декабря 2009

В дополнение к epoll похоже, что Linux sendfile(2) будет хорошо соответствовать вашим потребностям на стороне сервера.

2 голосов
/ 02 декабря 2009

В Linux sendfile() - это высокопроизводительный API, специально предназначенный для отправки данных из файлов в сокеты (вам все равно придется использовать poll для мультиплексирования, это просто замена части read / write ).

1 голос
/ 01 декабря 2009

В Windows вы можете попробовать TransmitFile , что может повысить вашу производительность, избегая копирования пространства <-> пространства пользователя в ядре.

0 голосов
/ 02 декабря 2009

Не оптимизируйте вашу программу преждевременно.

Если предположить, что это не преждевременная оптимизация, проще всего просто сохранить все данные в памяти. Вы можете mmap (), если хотите, или просто загрузить их во время запуска. Посылать то, что уже есть в памяти, не сложно.

Сказав, что попытка мультиплексировать множество вещей с (например, epoll) может быть головной болью, разве вы не можете использовать то, что уже написано?

0 голосов
/ 02 декабря 2009

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

Boost asio, вероятно, лучший вариант, если вам нужна мобильность (и простота использования), но у него есть свои ограничения, когда речь идет о многопоточной масштабируемости (см. C ++ Socket Server - Невозможно насыщать процессор ) - Думаю, основная проблема заключается в том, чтобы интегрировать обработку тайм-аута без чрезмерной блокировки в многопоточный цикл обработки событий.

По сути, для максимальной производительности вы хотели бы использовать порты завершения ввода-вывода с пулом рабочих потоков в Windows и Edge-инициируемый epoll с пулом рабочих потоков в Linux.

...