首页 > 其他分享 >golang 中使用 writev (sendmsg) 系统调用来一次发送多块数据

golang 中使用 writev (sendmsg) 系统调用来一次发送多块数据

时间:2023-10-27 18:00:12浏览次数:29  
标签:buf1 buf2 len writev golang start Error ivs 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)
		}
}

测试发现:

  1. 通过 sendmsg,减少了 conn.Write() 的调用次数,服务的性能明显上升;
  2. 当 buf1, buf2 对应的缓冲区,来自于 mmap() 调用时,零拷贝就生效了;
  3. 因为我测试的数据只有 2kb,所以使用零拷贝比不使用零拷贝更慢。(可能超过一定规模会更快)

标签:buf1,buf2,len,writev,golang,start,Error,ivs,sendmsg
From: https://www.cnblogs.com/ahfuzhang/p/17792911.html

相关文章

  • 云端golang开发,无需本地配置,能上网就能开发和运行
    欢迎访问我的GitHub这里分类和汇总了欣宸的全部原创(含配套源码):https://github.com/zq2599/blog_demos需求学习golang的时候,需要一个IDE,还需要一个能运行程序的环境,以及一个MySQL数据库对于有经验的程序员来说,自己动手安装部署即可,但是小白和懒人也是存在的...背景背......
  • golang 获取 mongo 数据库状态
    命令行模式navicatgolangpackagemainimport( "context" "encoding/json" "fmt" "log" "go.mongodb.org/mongo-driver/bson" "go.mongodb.org/mongo-driver/mongo" "go.mongodb.org/mongo-drive......
  • Nacos相关技术文档&Golang操作Nacos实现配置监听的代码
    Nacos相关技术文档Nacos中文文档~~~(三)Nacos开发教程之服务数据持久化(四)Nacos开发教程之SpringCloud集成服务注册(参考,后续用go实现)(五)Nacos开发教程之SpringCloud集成配置管理(参考,后续用go实现)(六)Nacos开发教程之后台系统使用~~~Mac-M1电脑本地使用docker搭建Nacos-Server参考:http......
  • golang的Leaf框架安装步骤
    最近在学习golang的Leaf游戏服务器框架(官方github),官方的安装步骤,非常简单,如下图:我在安装的时候也遇到一些疑问,因此记录下来我的实操步骤!1、我的现有GOPATH=E:\Go,src目录下有一些做过的项目2、获取LeafServer,我在src目录下clone的,遵循以前的原则,项目文件都放到GOPATH的src目录......
  • Golang Gin 实战(一)| 快速安装入门
    Gin 是一个非常优秀的GolangWebFramework,它不光API友好,性能也非常高,并且设计简洁,便于入门。所以它(Gin)非常受欢迎,在Github上已经三万三千多个星星,也是我最喜欢的Web框架。  入门要求要想使用GolangGin这个框架,你必须要得会Golang这门语言,如果你还没有开始学,我强烈推荐给你,......
  • golang validator 检验工具的使用指北
    golangvalidator包的使用指北原创阿兵云原生阿兵云原生2023-09-1009:27发表于广东看到validator咱们第一反应会想起啥?见名知意我就可以知道他是一个验证器,如果用过ginweb框架的同学,自然是用过gin里面的validator,只不过gin中使用的关键字是binding去做标识 ......
  • Golang logrus用法
    packagexlogimport( "bufio" "fmt" "github.com/sirupsen/logrus"rotatelogs"github.com/lestrrat-go/file-rotatelogs""github.com/rifflock/lfshook" "os" "time")typeConf......
  • Golang sync包中errgroup的使用详解
    WaitGroup主要用于控制任务组下的并发子任务。它的具体做法就是,子任务goroutine执行前通过Add方法添加任务数目,子任务goroutine结束时调用Done标记已完成任务数,主任务goroutine通过Wait方法等待所有的任务完成后才能执行后续逻辑packagemainimport("ne......
  • golang之xorm简单使用
    gogetgithub.com/go-xorm/xormpackagemainimport("fmt"_"github.com/go-sql-driver/mysql""github.com/go-xorm/xorm")typePointInfostruct{Idint64`xorm:"pkautoincr"`Product......
  • Systemd集成Golang二进制程序
    首先新建Service,名称叫做server-apivim/lib/systemd/system/server-api.service[Unit]Description=serverapi[Service]Type=simpleRestart=alwaysRestartSec=5sExecStart=/root/go/mainWorkingDirectory=/root/go/[Install]WantedBy=multi-user.targetExecStart......