qps测试epoll和io_uring

news2024/11/26 22:29:12

​ 前边我们了解了Reactor模式和Proactor模式,哪个性能更好呢?需要我们进行测试。前边我们用io_uring实现了Proactor模式,io_uring是2019年才加入到Linux内核中的,提供了三个系统调用函数。都有些抽象,我是直接来拿跑的。
​ 无论是我们epoll实现的Reactor模式还是io_uring实现的Proactor模式,两者都是服务器端。QPS:Queries Per Second意思是“每秒查询率”,是一台服务器每秒能够相应的查询次数,是对一个特定的查询服务器在规定时间内所处理流量多少的衡量标准。互联网中,作为域名系统服务器的机器的性能经常用每秒查询率来衡量。也就是说,qps这个参数是我们服务器端的一个重要性能。计算 qps的方法是通过统计在一定时间内处理的请求数,然后除以该时间间隔,得到平均每秒的请求数。
​ 我们可以写一个客户端的代码,分别对epoll实现的Reactor服务器和io_uring实现的Proactor服务器进行测试。客户端大致流程:对服务端发起请求到接收到服务器回发的数据,统计期间的时间。

​ 用getopt进行解析命令行参数
-t:表示线程数量
-c:表示连接数量
-n:表示请求数量

tcp客户端测试代码如下:

#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>


//定义函数计算两个时间结点的差(单位:毫秒)
#define TIME_SUB_MS(tv1, tv2)  ((tv1.tv_sec - tv2.tv_sec) * 1000 + (tv1.tv_usec - tv2.tv_usec) / 1000)

//结构体test_context_s定义线程入口函数(test_qps_entry)需要的变量
typedef struct test_context_s {

	char serverip[16];
	int port;
	int threadnum;
	int connection;
	int requestion;

#if 1
	int failed;
#endif
	
} test_context_t;

typedef struct test_context_s test_context_t;



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;
}



//定义测试发送数据 长度为64个字符
#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;


        //循环将字符串 TEST_MESSAGE 复制到 wbuffer 数组中
        //每次复制之前需要计算目标位置的偏移量(i * strlen(TEST_MESSAGE))
	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) {
		printf("failed: '%s' != '%s'\n", rbuffer, wbuffer);
		return -1;
	}
	
	return 0;
}


//线程入口函数
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;
        //识别信息 ./test_qps_tcpclient -s 192.168.147.129(看自己的主机地址,或者用回环地址127.0.0.1也行) -p 2048 -t 50 -c 100 -n 1000000
        //地址:192.168.147.129
        //连接的端口:2048
        //创建的线程数:50
		//连接数:100
		//请求数:1000000
        //赋值给对应的变量
	while ((opt = getopt(argc, argv, "s:p:t:c:n:?")) != -1) {
		switch (opt) {
                        //serverip:服务器ip地址
			case 's':
				printf("-s: %s\n", optarg);
				strcpy(ctx.serverip, optarg);
				break;
                        //port:服务器的端口
			case 'p':
				printf("-p: %s\n", optarg);
                                //atpi函数:将字符串转换成整数
				ctx.port = atoi(optarg);
				break;
                        //threadnum:线程数
			case 't':
				printf("-t: %s\n", optarg);
				ctx.threadnum = atoi(optarg);
				break;
                        //connection:连接数量
			case 'c':
				printf("-c: %s\n", optarg);
				ctx.connection = atoi(optarg);
				break;
                        //requestion:请求数量
			case 'n':
				printf("-n: %s\n", optarg);
				ctx.requestion = atoi(optarg);
				break;

			default:
				return -1;
		
		}
		
	}
        //为threadnum个线程的内存
	pthread_t *ptid = malloc(ctx.threadnum * sizeof(pthread_t));
	int i = 0;

	struct timeval tv_begin;
	gettimeofday(&tv_begin, NULL);

        //创建我们设定的线程数量,数量为threadnum
	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);

        //time_used单位是毫秒,要想计算qps,需要换算成秒,需要将请求数量*1000
	printf("success: %d, failed: %d, time_used: %d, qps: %d\n", ctx.requestion-ctx.failed, 
		ctx.failed, time_used, ctx.requestion * 1000 / time_used);


	free(ptid);
	return ret;
}



1.测试epoll实现的服务器的qps:
服务器端代码(在前边文章C语言实现Reactor中有)进行编译运行等待客户端连接(关闭服务器端所有日志信息)外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传

​ 上述客户端代码编译运行
外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传

2.测试io_uring实现的服务器的qps:
服务器端代码(在前边文章io_uring实现Proactor中有)进行编译运行等待客户端连接(关闭服务器端所有日志信息)
外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传

​ 上述客户端代码编译运行(注意修改自己服务器端代码中端口)
外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传

feXw-1724248941756)]

2.测试io_uring实现的服务器的qps:
服务器端代码(在前边文章io_uring实现Proactor中有)进行编译运行等待客户端连接(关闭服务器端所有日志信息)
[外链图片转存中…(img-5Ao2AjHx-1724248941756)]

​ 上述客户端代码编译运行(注意修改自己服务器端代码中端口)
[外链图片转存中…(img-XmFjRxwA-1724248941757)]

​ 通过上述测试,可以大致看出io_uring实现的异步Proactor性能的qps比epoll实现的同步Reactor性能要好。

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.coloradmin.cn/o/2060893.html

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

LLM驱动的AI Agent框架:引领行业变革的应用探索与未来展望

AI Agent框架&#xff08;LLM Agent&#xff09;&#xff1a;LLM驱动的智能体如何引领行业变革&#xff0c;应用探索与未来展望 1. AI Agent&#xff08;LLM Agent&#xff09;介绍 1.1. 术语 Agent&#xff1a;“代理” 通常是指有意行动的表现。在哲学领域&#xff0c;Agen…

视频直播平台选择服务器需要注意什么?

在当今数字化时代&#xff0c;直播平台已成为连接内容创作者与广大观众的重要桥梁。为了确保直播的流畅性、稳定性和安全性&#xff0c;服务器的选择与配置显得尤为重要。以下是搭建直播平台时&#xff0c;服务器所需具备的关键因素。 一、高性能与可扩展性 直播平台需要处理大…

黑神话悟空四十二项修改器 v1.0

软件简介 黑神话悟空四十二项修改器由风灵月影精心打磨&#xff0c;为《黑神话悟空》这款备受瞩目的游戏量身定制。这款修改器界面简洁、体积小巧、功能强大&#xff0c;它致力于为玩家提供便捷的游戏体验&#xff0c;让您能够根据个人喜好和需求&#xff0c;轻松调整游戏内的…

4-1-6 arduino控制42步进电机(电机专项教程)

4-1-6 arduino控制42步进电机&#xff08;电机专项教程&#xff09; 4-1-6 arduino控制42步进电机NEMA双极性步进电机A4988如何使用arduino连接A4988驱动模块Arduino控制Nema-17步进电机&#xff08;简化版&#xff09;A4988 Vref电压调节&#xff08;具体看视频&#xff09; 4…

Java数组05:Arrays类

本节内容视频链接&#xff1a;Java数组07&#xff1a;Arrays类讲解_哔哩哔哩_bilibilihttps://www.bilibili.com/video/BV12J41137hu?p57&vd_sourceb5775c3a4ea16a5306db9c7c1c1486b5 Java中的‌Array类是一个针对数组进行操作的工具类&#xff0c;‌提供了排序、‌…

SVG的基本图形:直线、圆、椭圆、矩形、多边形等的元素的使用说明。

1、先上个图看一下效果&#xff1a;这里面有直线、圆、矩形、椭圆、多边形。 SVG 可缩放矢量图形&#xff08;Scalable Vector Graphics&#xff09;。 SVG 使用 XML 格式定义图像。 2、代码实现&#xff1a; <svg width"500" height"200" viewBox&…

Kubernetes 如何给pod的 /etc/hosts文件里面添加条目

创建pod的时候&#xff0c;pod会在其/etc/hosts里面添加一个条目。 [rootmaster ~]# kubectl get pod -o wide NAME READY STATUS RESTARTS AGE IP NODE NOMINATED NODE READINESS GATES dns-test 1/1 R…

【RabbitMQ】高级特性

本文将介绍一些RabbitMQ的重要特性。 官方文档&#xff1a;Protocol Extensions | RabbitMQ 本文是使用的Spring整合RabbitMQ环境。 生产者发送确认(publish confirm) 当消息发送给消息队列&#xff0c;如何确保消息队列一定收到消息呢&#xff0c;RabbitMQ通过 事务机制 和 …

Java重修笔记 第三十八天 String翻转

String翻转 1. 要求将字符串指定的部分进行翻转 public class StringHomework {public static void main(String[] args) {// 要求将字符串指定的部分进行翻转// 例如:abcdef ---> a edcb f 1, 4System.out.print("转换前: ");String s "abcdef";…

Libcity笔记:strnn_encoder.py

1 cal_basetime 2 calc_timeoff 3 encode 所以对于 STRNN来说&#xff0c;它的eval_data的每个元素是&#xff1a;

《Python 异常捕获全解析及 yield 关键字详解》

在 Python 中&#xff0c;异常捕获是一种处理程序运行时错误的机制&#xff0c;它可以使程序在出现错误时继续运行&#xff0c;而不是崩溃。以下是对 Python 中异常捕获的详细介绍&#xff0c;包括try、except、else、finally关键字以及对yield关键字的介绍和案例。 一、异常捕…

深入解析FSD烟火识别算法:全套源码与应用实例

一、背景 随着智能监控技术的不断发展&#xff0c;烟火识别&#xff08;Fire Smoke Detection, FSD&#xff09;算法在安防领域得到了广泛应用。传统的火灾探测方法主要依赖于温度传感器和烟雾报警器&#xff0c;这些方法在反应速度和准确性上存在一定局限。尤其是在广阔的户外…

rocketmq 同步复制,异步复制,同步刷盘,异步刷盘详解

一、刷盘模式 同步刷盘&#xff1a; 在返回写成功状态时&#xff0c;消息已经被写入磁盘。具体流程是&#xff0c;消息写入内存的PAGECACHE后&#xff0c;立刻通知刷盘线程刷盘&#xff0c;然后等待刷盘完成&#xff0c;刷盘线程执行完成后唤醒等待的线程&#xff0c;返回消息…

Visual C++ 微软常用运行库合集|dll报错必装

前言 Microsoft Visual C Redistributable&#xff08;简称MSVC&#xff0c;VB/VC&#xff0c;系统运行库&#xff09;是Windows操作系统应用程序的基础类型库组件。此版Visual C运行库组件合集&#xff08;微软常用运行库合集&#xff09;由国内封装爱好者Dreamcast打包而成&…

VulnStack1-内网渗透记录

网络结构 kali192.168.20.145windows7192.168.20.148/192.168.52.1432008192.168.52.138Win2k3192.168.52.130 三台虚拟机IP初始状态固定为192.168.52.0/24网段&#xff0c;所以将仅主机模式的网卡设置为192.168.52.0/24网段 漏洞利用 phpStudy 首先查看windows7的web服务…

个人理解—uboot启动过程(1)

在前文关于MKCONFIG的常用配置参数与链接脚本中逐渐的引入了通过uboot的文件启动校验头引入了uboot的汇编部分&#xff0c;该部分是为了去启动后续的uboot的c语言部分&#xff0c;但是c语言是需要使用到内存的&#xff0c;所以可用理解为&#xff1a;该汇编部分的主要目的就是为…

python异步编程-channels使用,创建websocket服务

目录 channels介绍准备工作创建python虚拟环境安装channels安装django安装daphne创建django项目创建chat应用 配置instance项目简单聊天室页面在chat应用中创建模板base.htmlroom.html 添加视图添加路由添加urls.py项目路由添加chat转发路由启动同步服务器 搭建websocket服务创…

H5 Q绑查询系统源码

源码名称&#xff1a;H5 Q绑查询系统源码 源码介绍&#xff1a;H5Q绑查询系统源码由2个H5单页组成&#xff0c;无需数据库或PHP环境。上传后修改接口即可运行。 需求环境&#xff1a;H5 下载地址&#xff1a; https://www.51888w.com/208.html

鸿蒙内核源码分析(重定位篇) | 与国际接轨

一个程序从源码到被执行&#xff0c;当中经历了3个过程&#xff1a; 编译&#xff1a;将.c文件编译成.o文件&#xff0c;不关心.o文件之间的联系.静态链接&#xff1a;将所有.o文件合并成一个.so或.out文件&#xff0c;处理所有.o文件节区在目标文件中的布局.动态链接&#xf…

将所有PPT中的字体颜色白色改成黑色---使用AI提高效率

背景 在工作中&#xff0c;遇到一个PPT&#xff0c;老板需求&#xff0c;将PPT页面的所有的字体从白色改成黑色&#xff0c; 检查了发现&#xff0c;这个ppt有几个问题&#xff0c;没有使用母版&#xff0c;都是每一页进行编写&#xff0c; 一共500多页&#xff0c; 如果每个…