2008-12-11 4 views
5

Я создал клиент-серверную программу с Perl, используя IO :: Socket :: INET. Я обращаюсь к серверу через сайт CGI. Моя программа сервера будет работать как демон и будет принимать несколько одновременных соединений. Мой серверный процесс потребляет около 100 МБ пространства памяти (9 больших массивов, множество массивов ...). Я хочу, чтобы эти хэши проживали в памяти и делились ими, поэтому мне не нужно создавать их для каждого подключения. Создание хэша занимает 10-15 секунд.Как я могу обрабатывать несколько сокетов в демоне Perl с большим использованием памяти?

Всякий раз, когда новое соединение принимается через сокеты, я создаю новый процесс для обработки обработки для каждого полученного соединения. Поскольку родительский процесс огромен, каждый раз, когда я форк, процессор пытается выделить память новому ребенку, но из-за ограниченной памяти требуется много времени, чтобы создать нового ребенка, тем самым увеличивая время отклика. Много раз он зависает даже для одного соединения.

Родительский процесс создает 9 больших хэшей. Для каждого ребенка мне нужно обратиться к одному или нескольким хэшам в режиме только для чтения. Я не буду обновлять хэши через ребенка. Я хочу использовать что-то вроде copy-on-write, с помощью которого я могу обмениваться целыми 100mb или целыми глобальными переменными, созданными родителем со всем дочерним? или любой другой механизм, такой как потоки. Я ожидаю, что сервер получит минимум 100 запросов в секунду, и он должен будет обрабатывать все из них параллельно. В среднем, ребенок выйдет через 2 секунды.

Я использую Cygwin для Windows XP с 1 ГБ ОЗУ. Я не нашел возможности преодолеть эту проблему. Вы можете что-то предложить? Как я могу обмениваться переменными, а также создавать 100 дочерних процессов в секунду и управлять ими и синхронизировать их,

Спасибо.

ответ

3

Вместо разветвления есть два других подхода для обработки параллельных соединений. Либо вы используете потоки, либо опрос.

В поточном подходе для каждого соединения создается новый поток, который обрабатывает ввод-вывод сокета. Поток работает в той же виртуальной памяти процесса создания и может получить доступ ко всем своим данным. Убедитесь, что вы правильно используете блокировки для синхронизации доступа к записи.

Еще более эффективный подход - использовать опрос с помощью select(). В этом случае один процесс/поток обрабатывает все сокеты. Это работает в предположении, что большая часть работы будет I/O и что время, затраченное на ожидание завершения запросов ввода-вывода, будет потрачено на обработку других сокетов.

Пройдите исследование по этим двум вариантам и решите, какой из них вам подходит.

Смотрите, например: http://www.perlfect.com/articles/select.shtml

2

Если у вас есть, что много данных, интересно, почему вы не просто использовать базу данных?

2

Эта архитектура непригодна для Cygwin. Викинг на реальных Unix-системах дешев, но на поддельных системах Unix, таких как Cygwin, это ужасно дорого, потому что все данные должны быть скопированы (реальные инструменты используют copy-on-write). Использование потоков изменяет шаблон использования памяти (более высокое использование базы, но меньшее увеличение на поток), но вероятность того, что она все равно будет неэффективной.

Я бы посоветовал вам использовать однопроцессорный подход, используя опрос и, возможно, неблокирующий IO.

+0

Не является ли эмулированная версия Windows Perl для вилки нитью в том же процессе? Это немного меня немного, и это то, что я вспоминаю. – 2008-12-11 18:52:24