Я программирую что-то вроде 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
Это отлично помогло с утечкой памяти.