linux socket pipe,Golang socket 里面奇怪的 pipe 使用

有个 golang 写的 proxy server, 大概日常 tcp 连接数两万多左右,结果某次在 /proc/pid/fd 下面一看,竟然有五到六万多文件,ls -l 一看,居然 socket 只有两万多,pipe 反而有三万多小四万,这就奇了怪了,哪儿来的这么多 pipe?

读了一阵子源码搞清楚了,golang 在 Linux 下面,对于 fd 对拷这种操作【具体是 net.Conn.readFrom(net.Conn)】,有个用 splice 系统调用的优化,会先试着用 splice 调用在内核里面完成两个 fd 之间的拷贝,这个可以省去将大量数据从 kernel 里面拷贝到 user space 的操作。如果失败才正常拷贝。

然而 splice 这个调用可能是为了内部实现方便,目标一方必须是 pipe 类型的 fd。所以 golang 里面的实现其实比较龌龊,先创建一对 pipe fd,然后从源 fd splice 进 pipe 入端,接下来从 pipe 出端 splice 到目标 fd。 这样下来一个 readFrom 操作,里面要一次 pipe2 调用,2 次 splice 调用,还有 2 次 close 操作关掉 pipe。有趣的是,即使这么龌龊的实现,在数据量大的应用,比如 proxy 上面,依然可以达到比直接拷贝更好的性能,可以参考下面的第一个链接。

唯一感觉比较不爽的也就是每次 readFrom 都要创建 pipe 再销毁了,这个为了不影响 golang 的架构设计,可能也只能这么做。回头可能可以考虑自己专门写代码,把 proxy 部分的 io.Copy 替换掉来提高一些性能。

参考传送门

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值