网络框架netpoll中的SO_ZEROCOPY

2024-06-11 18:28
文章标签 框架 网络 netpoll zerocopy

本文主要是介绍网络框架netpoll中的SO_ZEROCOPY,希望对大家解决编程问题提供一定的参考价值,需要的开发者们随着小编来一起学习吧!

背景了解

https://www.163.com/dy/article/FS6AS7SS0518R7MO.html
https://docs.kernel.org/networking/msg_zerocopy.html

send() with MSG_ZEROCOPY

kernel v4.14 版本接受了来自 Google 工程师 Willem de Bruijn 在 TCP 网络报文的通用发送接口 send() 中实现的 zero-copy 功能
用户进程就能够把用户缓冲区的数据通过零拷贝的方式经过内核空间发送到网络套接字中去

因为前面几种零拷贝技术都是要求用户进程不能处理加工数据而是直接转发到目标文件描述符中去
Willem de Bruijn 在他的论文里给出的压测数据:
采用 netperf 大包发送测试,性能提升 39%,而线上环境的数据发送性能则提升了 5%~8%
官方文档陈述说这个特性通常只在发送 10KB 左右大包的场景下才会有显著的性能提升
一开始这个特性只支持 TCP,到内核 v5.0 版本之后才支持 UDP

这个功能的使用模式如下:
if (setsockopt(socket_fd, SOL_SOCKET, SO_ZEROCOPY, &one, sizeof(one)))
error(1, errno, “setsockopt zerocopy”);
ret = send(socket_fd, buffer, sizeof(buffer), MSG_ZEROCOPY);
// https://docs.kernel.org/networking/msg_zerocopy.html

第一步,先给要发送数据的 socket 设置一个 SOCK_ZEROCOPY option
第二步,在调用 send() 发送数据时再设置一个 MSG_ZEROCOPY option
其实理论上来说只需要调用 setsockopt() 或者 send() 时传递这个 zero-copy 的 option 即可
两者选其一,但是这里却要设置同一个 option 两次
官方的说法是为了兼容 send() API 以前的设计上的一个错误:send() 以前的实现会忽略掉未知的 option
为了兼容那些可能已经不小心设置了 MSG_ZEROCOPY option 的程序,设计成两步设置

猜测其他可能:
给使用者提供更灵活的使用模式,因为这个新功能只在大包场景下才可能会有显著的性能提升
现实场景很复杂:不仅仅是全部大包或者全部小包的场景,有可能是大包小包混合的场景
因此使用者可以先调用 setsockopt() 设置 SOCK_ZEROCOPY option
然后再根据实际业务场景中的网络包尺寸选择是否要在调用 send() 时使用 MSG_ZEROCOPY 进行 zero-copy 传输

注意:
send() 可能是异步发送数据,因此使用 MSG_ZEROCOPY 时,调用 send() 之后不能立刻重用或释放 buffer
因为 buffer 中的数据不一定已经被内核读走了,所以还需要从 socket 关联的队列里读取一下通知消息
看看 buffer 中的数据是否已经被内核读走

底层原理
这个技术是基于 redhat 红帽在 2010 年给 Linux 内核提交的 virtio-net zero-copy 技术之上实现的
通过 send() 把数据在用户缓冲区中的分段指针发送到 socket 中去
利用 page pinning <页锁定机制>锁住用户缓冲区的内存页
然后利用 DMA 直接在用户缓冲区通过内存地址指针进行数据读取,实现零拷贝
具体的细节可以通过阅读 Willem de Bruijn 的论文 (PDF)

主要缺陷:
(1) 只适用于大文件 (10KB 左右) 的场景,小文件场景因为 page pinning 页锁定和等待缓冲区释放的通知消息这些机制
甚至可能比直接 CPU 拷贝更耗时
(2) 因为可能异步发送数据,需要额外调用 poll() 和 recvmsg() 系统调用等待 buffer 被释放的通知消息,增加代码复杂度
以及会导致多次用户态和内核态的上下文切换;
(3) MSG_ZEROCOPY 目前只支持发送端,接收端暂不支持

绕过内核的直接 I/O
前面种种的 zero-copy 的方法,都是在想方设法地优化减少或者去掉用户态和内核态之间以及内核态和内核态之间的数据拷贝
为了实现避免这些拷贝可谓是八仙过海,各显神通,采用了各种各样的手段
那如果换个思路:这么费劲地去消除这些拷贝不就是因为有内核在掺和吗?

netpoll中的实现

初始化时的fd option设置

const (SO_ZEROCOPY       = 60SO_ZEROBLOCKTIMEO = 69MSG_ZEROCOPY      = 0x4000000
)func setZeroCopy(fd int) error {return syscall.SetsockoptInt(fd, syscall.SOL_SOCKET, SO_ZEROCOPY, 1)
}func setBlockZeroCopySend(fd int, sec, usec int64) error {return syscall.SetsockoptTimeval(fd, syscall.SOL_SOCKET, SO_ZEROBLOCKTIMEO, &syscall.Timeval{Sec:  sec,Usec: usec,})
}func (c *connection) init(conn Conn, opts *options) (err error) {... ...if setZeroCopy(c.fd) == nil && setBlockZeroCopySend(c.fd, defaultZeroCopyTimeoutSec, 0) == nil {c.supportZeroCopy = true}... ...
}

poll wait中的使用

仅关注 triggerWrite

// Wait implements Poll.
func (p 

这篇关于网络框架netpoll中的SO_ZEROCOPY的文章就介绍到这儿,希望我们推荐的文章对编程师们有所帮助!



http://www.chinasem.cn/article/1051944

相关文章

Debian 13升级后网络转发等功能异常怎么办? 并非错误而是管理机制变更

《Debian13升级后网络转发等功能异常怎么办?并非错误而是管理机制变更》很多朋友反馈,更新到Debian13后网络转发等功能异常,这并非BUG而是Debian13Trixie调整... 日前 Debian 13 Trixie 发布后已经有众多网友升级到新版本,只不过升级后发现某些功能存在异常,例如网络转

GSON框架下将百度天气JSON数据转JavaBean

《GSON框架下将百度天气JSON数据转JavaBean》这篇文章主要为大家详细介绍了如何在GSON框架下实现将百度天气JSON数据转JavaBean,文中的示例代码讲解详细,感兴趣的小伙伴可以了解下... 目录前言一、百度天气jsON1、请求参数2、返回参数3、属性映射二、GSON属性映射实战1、类对象映

Python开发简易网络服务器的示例详解(新手入门)

《Python开发简易网络服务器的示例详解(新手入门)》网络服务器是互联网基础设施的核心组件,它本质上是一个持续运行的程序,负责监听特定端口,本文将使用Python开发一个简单的网络服务器,感兴趣的小... 目录网络服务器基础概念python内置服务器模块1. HTTP服务器模块2. Socket服务器模块

解决若依微服务框架启动报错的问题

《解决若依微服务框架启动报错的问题》Invalidboundstatement错误通常由MyBatis映射文件未正确加载或Nacos配置未读取导致,需检查XML的namespace与方法ID是否匹配,... 目录ruoyi-system模块报错报错详情nacos文件目录总结ruoyi-systnGLNYpe

Go语言网络故障诊断与调试技巧

《Go语言网络故障诊断与调试技巧》在分布式系统和微服务架构的浪潮中,网络编程成为系统性能和可靠性的核心支柱,从高并发的API服务到实时通信应用,网络的稳定性直接影响用户体验,本文面向熟悉Go基本语法和... 目录1. 引言2. Go 语言网络编程的优势与特色2.1 简洁高效的标准库2.2 强大的并发模型2.

Python Web框架Flask、Streamlit、FastAPI示例详解

《PythonWeb框架Flask、Streamlit、FastAPI示例详解》本文对比分析了Flask、Streamlit和FastAPI三大PythonWeb框架:Flask轻量灵活适合传统应用... 目录概述Flask详解Flask简介安装和基础配置核心概念路由和视图模板系统数据库集成实际示例Stre

Olingo分析和实践之OData框架核心组件初始化(关键步骤)

《Olingo分析和实践之OData框架核心组件初始化(关键步骤)》ODataSpringBootService通过初始化OData实例和服务元数据,构建框架核心能力与数据模型结构,实现序列化、URI... 目录概述第一步:OData实例创建1.1 OData.newInstance() 详细分析1.1.1

Linux中压缩、网络传输与系统监控工具的使用完整指南

《Linux中压缩、网络传输与系统监控工具的使用完整指南》在Linux系统管理中,压缩与传输工具是数据备份和远程协作的桥梁,而系统监控工具则是保障服务器稳定运行的眼睛,下面小编就来和大家详细介绍一下它... 目录引言一、压缩与解压:数据存储与传输的优化核心1. zip/unzip:通用压缩格式的便捷操作2.

Spring 框架之Springfox使用详解

《Spring框架之Springfox使用详解》Springfox是Spring框架的API文档工具,集成Swagger规范,自动生成文档并支持多语言/版本,模块化设计便于扩展,但存在版本兼容性、性... 目录核心功能工作原理模块化设计使用示例注意事项优缺点优点缺点总结适用场景建议总结Springfox 是

Python的端到端测试框架SeleniumBase使用解读

《Python的端到端测试框架SeleniumBase使用解读》:本文主要介绍Python的端到端测试框架SeleniumBase使用,具有很好的参考价值,希望对大家有所帮助,如有错误或未考虑完全... 目录SeleniumBase详细介绍及用法指南什么是 SeleniumBase?SeleniumBase