performance - 糟糕的haskell网络性能

标签 performance networking haskell

我正在编写一些“类似openvpn”的东西,并认为这将是提高我的Haskell知识的好人选。但是,我遇到了相当严重的性能问题。

它的作用:它打开一个 TUN 设备;它将自身绑定(bind)在 UDP 端口上,启动 2 个线程(forkIO,但是由于 fdRead 使用 -thread 编译)。我没有使用过 tuntap 包,完全是在 Haskell 中自己完成的。

线程 1:从 tun 设备读取数据包(fdRead)。使用 UDP 套接字发送它。
线程 2:从 UDP 套接字读取数据包(recv);将其发送到 tun 设备 (fdWrite)

问题 1:在此配置中,fdRead 返回字符串,并且我使用了接受字符串的 Network.Socket 函数。我在本地系统上进行了配置(一些 iptables 魔术),我可以通过它在 localhost 上运行 15MB/s,程序基本上在 100% CPU 上运行。那很慢。我可以做些什么来提高性能吗?

问题 2:我必须在发送的数据包中添加一些内容;但是 sendMany 网络函数只需要 ByteString;从 Fd 读取返回字符串。转换很慢。使用 TUN 设备转换为 Handle 似乎不够好......

问题 3:我想在 Data.Heap(功能堆)中存储一些信息(我需要使用“takeMin”,虽然对于 3 个项目来说它是矫枉过正,但很容易做到:))。所以我创建了一个 MVar 并且在每个接收到的数据包上我都从 MVar 中提取了堆,用新信息更新了堆并将其放回 MVar 现在事情开始消耗大量内存。可能是因为旧堆没有足够快/足够频繁地收集垃圾..?

有没有办法解决这些问题,还是我必须回到 C ......?我正在做的应该主要是零拷贝操作——我是否使用了错误的库来实现它?

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

我做了什么:
- 当放入 MVar 时,做了:

a `seq` putMVar mvar a

这完全有助于解决内存泄漏。
  • 改为字节串;现在我只使用“读/写”而不进行进一步处理时得到 42MB/s。 C 版本的速度约为 56MB/s,因此这是可以接受的。
  • 最佳答案

    字符串很慢。真的,真的,真的很慢。它是一个包含一个 unicode 字符的 cons 单元的单链接列表。将一个写入套接字需要将每个字符转换为字节,将这些字节复制到一个数组中,然后将该数组交给系统调用。这听起来像是你想做的事情的哪一部分? :)

    您想独占使用 ByteString。 ByteString IO 函数实际上尽可能使用零拷贝 IO。尤其是看network-bytestring hackage 包。它包含所有经过优化以有效使用 ByteString 的网络库的版本。

    关于performance - 糟糕的haskell网络性能,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/4228416/

    相关文章:

    android - 使用 libgdx 绘制大背景图像 - 最佳实践?

    MySQL 慢查询

    performance - 为什么(在 MATLAB 中)这段代码更快?

    c++ - 一个程序对应于另一个c++的位置

    linux - 如何使用 bash 知道连接到每个 SSID 的客户端数量?

    c - sysfs、ifreq、IOCTL 或 ???以编程方式监控网络状态

    haskell - 在 Haskell 中的列表末尾添加一个元素

    java - JnetPcap:从脱机文件读取速度非常慢

    haskell - Haskell 中的幻像类型

    haskell - Haskell 中地板和 sqrt 的联合使用