Низкая производительность сети haskell

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

Что он делает: открывает устройство TUN; он связывает себя с портом UDP, запускает 2 потока (forkIO, однако скомпилированный с помощью -threaded из-за fdRead). Я не использовал пакет tuntap и сделал это сам полностью на Haskell.

поток 1: чтение пакета (fdRead) с устройства tun. Отправьте его через сокет UDP.
поток 2: прочитать пакет (recv) из сокета UDP; отправить его на устройство tun (fdWrite)

Проблема 1: В этой конфигурации fdRead возвращает String, и я использовал функции Network.Socket, которые принимают String. Я сделал конфигурацию в локальной системе (немного магии iptables), и я могу запустить через нее 15 МБ / с на локальном хосте, программа работает в основном на 100% ЦП. Это медленно. Могу ли я что-нибудь сделать для повышения производительности?

Проблема 2: Мне нужно будет что-то добавить к отправляемым мной пакетам; однако сетевая функция sendMany принимает только ByteString; чтение из Fd возвращает String. Конверсия идет довольно медленно. Преобразование в Handle, похоже, недостаточно хорошо работает с устройством TUN ....

Проблема 3: Я хотел сохранить некоторую информацию в Data.Heap (функциональная куча) (мне нужно использовать 'takeMin' и хотя по 3 пунктам это перебор, но сделать это несложно :)). Итак, я создал MVar, и для каждого полученного пакета я извлек кучу из MVar, обновил кучу новой информацией и поместил ее обратно inito MVar. Теперь вещь просто начинает съедать много памяти. Вероятно, потому что старые кучи не собирают мусор быстро / достаточно часто…?

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

==================

Что я сделал: не собирать мусор быстро / достаточно часто ..?

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

==================

Что я сделал: не собирать мусор быстро / достаточно часто ..?

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

==================

Что я сделал: - при установке в MVar сделал:

a `seq` putMVar mvar a

Это отлично помогло с утечкой памяти.

  • изменено на ByteString; теперь я получаю 42 МБ / с при использовании только «чтения / записи» без дальнейшей обработки. Версия C обеспечивает скорость около 56 МБ / с, поэтому это приемлемо.
12
задан Don Stewart 2 May 2011 в 21:32
поделиться