手撕测试tcp服务器效率工具——以epoll和io_uring对比为例

这篇具有很好参考价值的文章主要介绍了手撕测试tcp服务器效率工具——以epoll和io_uring对比为例。希望对大家有所帮助。如果存在错误或未考虑完全的地方,请大家不吝赐教,您也可以点击"举报违法"按钮提交疑问。

服务器性能测试介绍

服务器的性能测试主要包括2部分:

  1. 并发量。能容纳多大的连接
  2. 效率。在不崩坏的情况下能对报文的处理效率。

本文主要进行效率测试,看看基于epoll模型和io_uring模型的tcp服务器,谁的效率更高。

测试思路

客户端(一个或多个)大量地向服务器发送报文,测试服务器的处理效率(tps:transaction per second,qps:queries per second)。这个或这些客户端也被成为测试工具。

测试工具需求

1、  基于tcp

2、  可以设置请求、线程与连接的数量。-n req -t threadnum -c connection。

在本文中,为了方便,我们为一个连接建立一个线程,也就是线程和连接一一对应。

getopt是一个解析命令行参数的函数,它不是一个线程安全的函数,尽量只在1个线程中使用,建议提前了解。

测试工具代码

代码有详细地注释,主要步骤为:

1、解析命令行参数,看看服务器的IP和port,以及要建立多少连接、发送多少数据等。

2、根据线程数建立线程,在线程里建立一个连接,连接服务器,并按每个线程的平均发送数据任务不间断地发送数据和接收数据。本案例中每笔报文的大小为64*8。

3、计算从开始发送到结束接收的耗时,并计算相关指标。

服务器的功能是:接收到什么数据就返回什么数据。

详细的服务器代码可看前文:

与epoll媲美的io_uring_io_uring tcp服务器-CSDN博客

用反应器模式和epoll构建百万并发服务器_如何设计一个支持百万并发的服务器-CSDN博客

#include<stdio.h>
#include<string.h>
#include<sys/socket.h>
#include<stdlib.h>
#include<unistd.h>

#include<sys/time.h>
#include<pthread.h>
#include<arpa/inet.h>

//设置该结构体用于存储线程函数所需的参数
typedef struct test_context_s{
	
	char serverip[16]; //服务器ip
	int port;	//服务器端口
	int threadnum;	//线程数量
	int connection;	//连接数量,此案例中与线程数量一致
	int requestion;	//请求数量,也就是报文数量
	
	int failed; //统计发送失败的次数,有个大概的数就行,所以没用原子变量
}test_context_t;

typedef struct test_context_s test_context_t;

//与服务器建立tcp连接,常规的socket然后connect
int connect_tcpserver(const char* ip,unsigned short port){
	
	int connfd = socket(AF_INET,SOCK_STREAM,0);

	struct sockaddr_in tcpserver_addr;
	memset(&tcpserver_addr,0,sizeof(struct sockaddr_in));

	tcpserver_addr.sin_family = AF_INET;
	tcpserver_addr.sin_addr.s_addr = inet_addr(ip);
	tcpserver_addr.sin_port = htons(port);

	int ret = connect(connfd,(struct sockaddr*)&tcpserver_addr,sizeof(struct sockaddr_in));

	if(ret){
		perror("connect");
		return -1;
	}
	return connfd;
}

#define TIME_SUB_MS(tv1,tv2) ((tv1.tv_sec - tv2.tv_sec)*1000 + (tv1.tv_usec - tv2.tv_usec)/1000)

//要发送给客户端的数据的基本单位
#define TEST_MESSAGE   "ABCDEFGHIJKLMNOPQRSTUVWXYZ1234567890abcdefghijklmnopqrstuvwxyz\r\n"

#define RBUFFER_LENGTH 2048 //读数据的空间的大小,不一定用满
#define WBUFFER_LENGTH 2048 //写数据的空间的大小,不一定用满

//客户端发送并接收数据
int send_recv_tcppkt(int fd){
	char wbuffer[WBUFFER_LENGTH] = {0};

	//设置每次发送的报文包含多少个基本单位
	int i = 0;
	for(i=0;i<8;i++){
		strcpy(wbuffer+i *strlen(TEST_MESSAGE),TEST_MESSAGE);
	}

	//发送报文
	int res = send(fd,wbuffer,strlen(wbuffer),0);
	if(res<0){
		exit(1);
	}

	//接收报文
	char rbuffer[RBUFFER_LENGTH] ={0};
	res = recv(fd,rbuffer,RBUFFER_LENGTH,0);
	if(res<=0){
		exit(1);
	}

	if(strcmp(rbuffer,wbuffer)!=0){
		return -1;
	}
	
}


//线程函数,主要作用是建立连接、发送接收报文
static void *test_qps_entry(void* arg){
	
	test_context_t *pctx = (test_context_t*)arg;

	//建立连接
	int connfd = connect_tcpserver(pctx->serverip,pctx->port);
	if(connfd<0){
		printf("connect_tcpserver failed!\n");
		return NULL;
	} 

	//每个线程要发送的报文数量
	int count = pctx->requestion/pctx->threadnum;

	//发送报文
	int i=0;
	int res;
	while(i++<count){
		res = send_recv_tcppkt(connfd);
		if(res!=0){
			printf("send_recv_tcppkt failed\n");
			pctx->failed++;
			continue;
		}
	}
	return NULL;
}

int main(int argc,char *argv[]){
	
	int ret =0;
	test_context_t ctx ={0};
	
	int opt;
	
	//getopt函数可以一次解析出带有名称的输入参数
	//注意这个函数是线程不安全的,
	while((opt = getopt(argc,argv,"s:p:t:c:n:?"))!=-1){
		switch(opt){
			case 's':
				printf("-s:%s\n",optarg);
				strcpy(ctx.serverip,optarg);//服务器IP
				break;		
			 case 'p':
				printf("-p:%s\n",optarg);
				ctx.port = atoi(optarg);//服务器端口
				break;
			case 't':    
				printf("-t:%s\n",optarg);
				ctx.threadnum = atoi(optarg);//线程数
				break;
			case 'c':
				printf("-c:%s\n",optarg);
				ctx.connection = ctx.threadnum;//还是和线程数一致吧	
				break;
			case 'n':
				printf("-n:%s\n",optarg);
				ctx.requestion = atoi(optarg);
				break;
			default:
				return -1;					
		}
	}

	//线程数组
	pthread_t *ptid = malloc(ctx.threadnum *sizeof("pthread_t"));

	//开始大规模发送发送报文
	struct timeval tv_begin;	//记录报文开始发送的时间
	gettimeofday(&tv_begin,NULL);

	int i = 0;
	for(i=0;i<ctx.threadnum;i++){	//建立线程运行线程函数
		pthread_create(&ptid[i],NULL,test_qps_entry,&ctx);
	}

	for(i=0;i<ctx.threadnum;i++){
		pthread_join(ptid[i],NULL);
	}

	struct timeval tv_end;	//记录报文全部发送并接收完毕的时间
	gettimeofday(&tv_end,NULL);

	int time_used = TIME_SUB_MS(tv_end,tv_begin);//计算用时

	printf("success: %d, failed: %d, time_used: %d, qps: %d\n", ctx.requestion-ctx.failed, 
		ctx.failed, time_used, ctx.requestion * 1000 / time_used);

	return 0;

}

测试结果

epoll服务器

手撕测试tcp服务器效率工具——以epoll和io_uring对比为例,tcp/ip,服务器,网络协议,c语言,linux,运维,c++

发送了100w数据,qps为33243

io_uring服务器

手撕测试tcp服务器效率工具——以epoll和io_uring对比为例,tcp/ip,服务器,网络协议,c语言,linux,运维,c++

发送了100w数据,qps为43305

结论

在本机、本案例的情况下,io_uring服务器的效率比epoll服务器的效率高约30%。文章来源地址https://www.toymoban.com/news/detail-799721.html

到了这里,关于手撕测试tcp服务器效率工具——以epoll和io_uring对比为例的文章就介绍完了。如果您还想了解更多内容,请在右上角搜索TOY模板网以前的文章或继续浏览下面的相关文章,希望大家以后多多支持TOY模板网!

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处: 如若内容造成侵权/违法违规/事实不符,请点击违法举报进行投诉反馈,一经查实,立即删除!

领支付宝红包 赞助服务器费用

相关文章

  • TCP服务器的演变过程:使用epoll构建reactor网络模型实现百万级并发(详细代码)

    手把手教你从0开始编写TCP服务器程序,体验开局一块砖,大厦全靠垒。 为了避免篇幅过长使读者感到乏味,对【TCP服务器的开发】进行分阶段实现,一步步进行优化升级。 本节,在上一章节介绍了如何使用epoll开发高效的服务器,本节将介绍使用epoll构建reactor网络模型,实

    2024年02月01日
    浏览(72)
  • epoll实现并发服务器

    epoll 是Linux操作系统提供的一种事件通知机制,用于高效处理大量文件描述符上的事件。它是一种基于内核的I/O事件通知接口,可以用于实现高性能的并发服务器和异步I/O操作。 与传统的事件通知机制(如 select 和 poll )相比, epoll 具有更高的性能和扩展性。它采用了一种基

    2024年02月09日
    浏览(52)
  • epoll并发服务器的实现

    1.实现并发通信的三种方式 ​ 实现并发通信主要有三种方式: 多进程服务器 、 多路复用服务器 (I/O复用)、 多线程服务器 多进程服务器 ​ 多进程服务器指的是利用不同进程处理来自不同客户端发来的连接请求,进程之间以轮转的方式运行,由于各个进程之间轮转运行的时

    2024年02月03日
    浏览(57)
  • 基于epoll实现Reactor服务器

    在我们调用epoll_create的时候会创建出epoll模型,这个模型也是利用文件描述类似文件系统的方式控制该结构。 在我们调用epoll_create的时候,就会在内核管理中创建一个epoll模型,并且建管理模块地址给file结构体,file结构体也是连接在管理所有file结构体的数据结构中 所以epo

    2024年02月20日
    浏览(42)
  • epoll多路复用_并发服务器

    应用程序: 驱动程序:

    2024年02月15日
    浏览(53)
  • 2023.7.30(epoll实现并发服务器)

    服务器 客户端

    2024年02月14日
    浏览(43)
  • iperf3测试服务器tcp带宽udp丢包率

    要使用 iperf 测试网络的性能,您需要两台计算机,一台作为服务器,一台作为客户端,这将帮助您测试两台主机之间的网段。特别注意的是两台计算机的网口一定是同样的网口,测试的数据才是准确的,我之前测试的时候服务器端网口是万兆的,客户端用的是千兆的,所以测

    2024年02月12日
    浏览(44)
  • 【基于C++HTTP 服务器的epoll 改造】

    打印模块 Log.hpp 方便使用 TcpServer.hpp HttpServer.hpp Task.hpp ThreadPool.hpp Util.hpp Protocol.hpp Makefile main.cc 后续加上post 请求 原文链接: link

    2024年02月02日
    浏览(71)
  • 多路IO—POll函数,epoll服务器开发流程

    \\\"在计算机网络编程中,多路IO技术是非常常见的一种技术。其中,Poll函数和Epoll函数是最为常用的两种多路IO技术。这两种技术可以帮助服务器端处理多个客户端的并发请求,提高了服务器的性能。本文将介绍Poll和Epoll函数的使用方法,并探讨了在服务器开发中使用这两种技

    2024年02月06日
    浏览(40)
  • I/O多路转接——epoll服务器代码编写

    目录 一、poll​ 二、epoll 1.epoll 2.epoll的函数接口 ①epoll_create ②epoll_ctl ③epoll_wait 3.操作原理 三、epoll服务器编写 1.日志打印 2.TCP服务器 3.Epoll ①雏形 ②InitEpollServer 与 RunServer ③HandlerEvent 四、Epoll的工作模式 1.LT模式与ET模式 2.基于LT模式的epoll服务器 ①整体框架 ②处理BUG ③优

    2024年02月02日
    浏览(50)

觉得文章有用就打赏一下文章作者

支付宝扫一扫打赏

博客赞助

微信扫一扫打赏

请作者喝杯咖啡吧~博客赞助

支付宝扫一扫领取红包,优惠每天领

二维码1

领取红包

二维码2

领红包