golang 中使用 writev (sendmsg) 系统调用来一次发送多块数据
作者:张富春(ahfuzhang),转载时请注明作者和引用链接,谢谢!
writev,或者说 sendmsg 等系统调用,能够发送多个数据块。从节约系统调用次数的角度说,这个 api 非常好。
下面演示如何在 golang 中使用 sendmsg 系统调用:
func sendmsg(conn net.Conn, buf1 []byte, buf2 []byte){
// 我的应用里正好只有两块数据,所以偷懒了
// 先获得 socket fd
rawConn, err := sysconn.SyscallConn()
if err != nil {
log.Error(err.Error())
return
}
var sockfd uintptr
err = rawConn.Control(func(fd uintptr) {
sockfd = fd
})
if err != nil {
log.Error(err.Error())
return
}
//
//send msg
var ivs [2]syscall.Iovec
start := 0
total := len(buf1) + len(buf2)
var cnt uint64 = 2
for start < total {
if start < len(buf1) {
ivs[0].Base = &buf1[start]
ivs[0].Len = uint64(len(buf1) - start)
ivs[1].Base = &buf2[0]
ivs[1].Len = uint64(len(buf2))
} else {
cnt = 1
ivs[0].Base = &buf2[start-len(buf1)]
ivs[0].Len = uint64(len(buf1)+len(buf2)-start)
}
var msghdr = syscall.Msghdr{
Iov: &ivs[0],
Iovlen: cnt,
}
var flags uintptr = 0x4000000 // 零拷贝标志
r, _, e := syscall.RawSyscall(syscall.SYS_SENDMSG, sockfd, uintptr(unsafe.Pointer(&msghdr)), flags)
if e != 0 {
log.Error(syscall.Errno(e).Error())
return
}
start += int(r)
}
}
测试发现:
- 通过 sendmsg,减少了 conn.Write() 的调用次数,服务的性能明显上升;
- 当 buf1, buf2 对应的缓冲区,来自于 mmap() 调用时,零拷贝就生效了;
- 因为我测试的数据只有 2kb,所以使用零拷贝比不使用零拷贝更慢。(可能超过一定规模会更快)
golang 中使用 writev (sendmsg) 系统调用来一次发送多块数据的更多相关文章
- TCP层sendmsg系统调用的实现分析
概述 sendmsg系统调用在tcp层的实现是tcp_sendmsg函数,该函数完成以下任务:从用户空间读取数据,拷贝到内核skb,将skb加入到发送队列的任务,调用发送函数:函数在执行过程中会锁定控 ...
- 套接字之sendmsg系统调用
sendmsg系统调用允许在用户空间构造消息头和控制信息,用此函数可以发送多个数据缓冲区的数据,并支持控制信息:当调用进入内核后,会将用户端的user_msghdr对应拷贝到内核的msghdr中,然后 ...
- golang中的race检测
golang中的race检测 由于golang中的go是非常方便的,加上函数又非常容易隐藏go. 所以很多时候,当我们写出一个程序的时候,我们并不知道这个程序在并发情况下会不会出现什么问题. 所以在本 ...
- 基础知识 - Golang 中的正则表达式
------------------------------------------------------------ Golang中的正则表达式 ------------------------- ...
- golang中的reflect包用法
最近在写一个自动生成api文档的功能,用到了reflect包来给结构体赋值,给空数组新增一个元素,这样只要定义一个input结构体和一个output的结构体,并填写一些相关tag信息,就能使用程序来生 ...
- Golang中的坑二
Golang中的坑二 for ...range 最近两周用Golang做项目,编写web服务,两周时间写了大概五千行代码(业务代码加单元测试用例代码).用Go的感觉很爽,编码效率高,运行效率也不错,用 ...
- Golang 中的坑 一
Golang 中的坑 短变量声明 Short variable declarations 考虑如下代码: package main import ( "errors" " ...
- google的grpc在golang中的使用
GRPC是google开源的一个高性能.跨语言的RPC框架,基于HTTP2协议,基于protobuf 3.x,基于Netty 4.x. 前面写过一篇golang标准库的rpc包的用法,这篇文章接着讲一 ...
- Golang中Struct与DB中表字段通过反射自动映射 - sqlmapper
Golang中操作数据库已经有现成的库"database/sql"可以用,但是"database/sql"只提供了最基础的操作接口: 对数据库中一张表的增删改查 ...
- Golang中WaitGroup使用的一点坑
Golang中WaitGroup使用的一点坑 Golang 中的 WaitGroup 一直是同步 goroutine 的推荐实践.自己用了两年多也没遇到过什么问题.直到一天午睡后,同事扔过来一段奇怪的 ...
随机推荐
- 火山引擎 DataTester:A/B 实验如何实现人群智能化定向?
更多技术交流.求职机会,欢迎关注字节跳动数据平台微信公众号,回复[1]进入官方交流群 在精细化运营时代,用户需求和业务场景愈加多元,在产品功能迭代以及各类活动中,面向不同人群的兴趣点,有针对性地&qu ...
- linux 实时刷新显示当前时间
同步阿里云时间 ntpdate ntp1.aliyun.com 使用watch命令:周期性的执行一个命令,并全屏显示. watch -n 1 date 即可:每1秒刷新date命令. # 格式 wat ...
- Intellij 查找排除JAR包的依赖关系(Maven Helper)
Intellij 查找排除JAR包的依赖关系(Maven Helper) 安装插件 Windows 类似
- 用Python学线性代数:概率密度函数拟合
问题 如果有一组数据,如何确定他们来自哪个统计分布? 从数据分析的角度,我们并不想要通过严格的统计方法去找到这个分布,Python中有一个可以自动拟合数据分析的库 -- distfit .这是一个py ...
- vim-修改键盘Tab键为四个空格
在 /etc/vimrc 文件后添加一行 set ts=4
- Linux 网络收包流程
哈喽大家好,我是咸鱼 我们在跟别人网上聊天的时候,有没有想过你发送的信息是怎么传到对方的电脑上的 又或者我们在上网冲浪的时候,有没有想过 HTML 页面是怎么显示在我们的电脑屏幕上的 无论是我们跟别人 ...
- 2021杭电多校第零场 & 2021湘潭全国邀请赛 补题记录
比赛链接:Here 本场题目重现于 2021湘潭全国邀请赛 A - A+B Problem (签到) 根据题意处理即可 int main() { cin.tie(nullptr)->sync_w ...
- 素数算法补充之"筛法"
国庆中秋双节,就不写太长的文章了. 补充和复习一下以前没写的素数区间筛法算法吧 部分证明过程来自OI wiki 素数筛法 如果我们想要知道小于等于 \(n\) 有多少个素数呢? 一个自然的想法是我们对 ...
- 二、swift添加存储策略
系列导航 一.swift对象存储环境搭建 二.swift添加存储策略 三.swift大对象--动态大对象 四.swift大对象--静态态大对象 五.java操作swift对象存储(官网样例) 六.ja ...
- 使用element-plus的el-scrollbar时滚动条没有显示出来但是页面可以滚动的解决办法
如果使用 Element UI 的 el-scrollbar 组件时,滚动条没有显示出来但页面可以滚动,可以尝试调用其 update 方法来更新滚动条. 在适当的时机(例如在数据加载完成后或组件更新后 ...
