泰安企业网站建设公司,广西网站开发,墨玉县建设工程信息网,网络编程技术期末考试前言
接着上篇文章#xff0c;rte_timer的性能测试https://blog.csdn.net/jacicson1987/article/details/144997298
进行常用的libevent的定时器测试#xff0c;看看有什么区别#xff0c;测试方法还是一样#xff0c;代码放在下面。
测试方法
100万个定时器#xff0…前言
接着上篇文章rte_timer的性能测试https://blog.csdn.net/jacicson1987/article/details/144997298
进行常用的libevent的定时器测试看看有什么区别测试方法还是一样代码放在下面。
测试方法
100万个定时器设置超时回调后继续set定时器 不停循环。
测试代码
#include stdio.h
#include stdint.h
#include pthread.h
#include signal.h
#include unistd.h
#include sys/time.h#include rte_mempool.h
#include rte_timer.h
#include rte_eal.h
#include rte_launch.h
#include rte_cycles.h
#include rte_malloc.h
#include rte_lcore.h#include event2/event.h
#include event2/event_struct.h#define NUM_WORKERS 5
#define NUM_TIMERS_PER_WORKER 1000000
#define TIMER_RATE_PER_SECOND 25000// 定时器参数
#define TIMEOUT_SEC 60 // 超时秒// 定义一个存储定时器的结构体
typedef struct {struct rte_timer timer; // DPDK 定时器struct event timer_event; // libevent 定时器uint64_t id; // 唯一标识符
} timer_data;int quit 0;#define TIMER_NUM (NUM_WORKERS * NUM_TIMERS_PER_WORKER)struct rte_mempool *timer_mempool;static void signal_handler(int signal) {switch (signal) {case SIGINT:case SIGTERM:printf(\n\nSignal %d received, preparing to exit...\n, signal);quit true;break;default:break;}
}// 定时器回调函数
static void timer_callback(struct rte_timer *timer, void *arg) {timer_data *data (timer_data *)arg;// 重设定时器//printf(timer_callback\n);rte_timer_reset(timer, TIMEOUT_SEC * rte_get_timer_hz(), SINGLE, rte_lcore_id(), timer_callback, data);
}static inline int set_timer(int lcore_id)
{int ret 0;void* td;ret rte_mempool_get(timer_mempool, td);if (ret ! 0) {printf(Error: get timer from pool failed\n);return -1;}ret rte_timer_reset(((timer_data*)td)-timer, TIMEOUT_SEC* rte_get_timer_hz(), SINGLE, lcore_id, timer_callback, td);if (ret ! 0) {printf(Error: rte_timer_reset failed %d\n, lcore_id);return -1;}return 0;
}static int set_timers_worker(__rte_unused void *dummy)
{printf(Starting set_timer_worker on core %u\n, rte_lcore_id());struct timeval start_time, end_time;gettimeofday(start_time, NULL);uint64_t start_tick rte_rdtsc();int i 0, ret 0; int lcore_id rte_lcore_id();for (i 0; i NUM_TIMERS_PER_WORKER; i) {ret set_timer(lcore_id);if (ret ! 0) {return -1;}usleep(10);}uint64_t end_tick rte_rdtsc();gettimeofday(end_time, NULL);double elapsed_time (end_time.tv_sec - start_time.tv_sec) (end_time.tv_usec - start_time.tv_usec) / 1000000.0;uint64_t elapsed_tick end_tick - start_tick;double elapsed_s (elapsed_tick*1000 / rte_get_timer_hz())/1000.0;printf(Finish set timer on core %u, cost %.3f %.3f\n, rte_lcore_id(), elapsed_time, elapsed_s);while (!quit) {rte_timer_manage();rte_delay_ms(10);}return 0;
}static void ev_timer_callback(evutil_socket_t fd, short event, void *arg)
{timer_data* td (timer_data*)arg;struct timeval time_out;time_out.tv_sec TIMEOUT_SEC;time_out.tv_usec 0;evtimer_add(td-timer_event, time_out);//printf(ev_timer_callback\n);
}int ev_set_timer(struct event_base* base)
{int ret 0;void* td;ret rte_mempool_get(timer_mempool, td);if (ret ! 0) {printf(Error: get timer from pool failed\n);return -1;}struct event* timer ((timer_data*)td)-timer_event;evtimer_assign(timer, base, ev_timer_callback, td);struct timeval time_out;time_out.tv_sec TIMEOUT_SEC;time_out.tv_usec 0;evtimer_add(timer, time_out);return 0;
}static int ev_set_timers_worker(__rte_unused void *dummy)
{int i 0, ret 0;printf(Starting ev_set_timer_worker on core %u\n, rte_lcore_id());struct event_base* base event_base_new();struct timeval start_time, end_time;gettimeofday(start_time, NULL);for (i 0; i NUM_TIMERS_PER_WORKER; i) {ret ev_set_timer(base);if (ret ! 0) {return -1;}usleep(10);}gettimeofday(end_time, NULL);double elapsed_time (end_time.tv_sec - start_time.tv_sec) (end_time.tv_usec - start_time.tv_usec) / 1000000.0;printf(inish set timer on core %u, cost %.3f \n, rte_lcore_id(), elapsed_time);while (!quit) {event_base_loop(base, EVLOOP_NONBLOCK);rte_delay_ms(10);}
}
/*
* command:
* ./timertest -l 1 -n 2 --proc-typeauto
*/
int main(int argc, char *argv[]) {int ret;pthread_t worker_threads[NUM_WORKERS];uint64_t core_id;// 初始化 DPDK 环境ret rte_eal_init(argc, argv);if (ret 0) {rte_exit(EXIT_FAILURE, EAL initialization failed\n);}// 初始化定时器运行环境rte_timer_subsystem_init();// 创建一个内存池来存储定时器数据timer_mempool rte_mempool_create(timer_mempool, TIMER_NUM, sizeof(timer_data), 0, 0, NULL, NULL, 0, 0, rte_socket_id(), 0);if (timer_mempool NULL) {rte_exit(EXIT_FAILURE, Failed to create mempool\n);}//set_timers_worker(NULL);ev_set_timers_worker(NULL);return 0;
}
Makefile
其中libevent使用静态连接方便后续观察
APP_tool timertest#SRCS-y $(wildcard *.c)
SRCS-t $(wildcard *.c)
PKGCONF ? pkg-configCFLAGS -g -O2 $(shell $(PKGCONF) --cflags libdpdk)
LDFLAGS -Wl,-Bstatic -levent -Wl,-Bdynamic $(shell $(PKGCONF) --libs libdpdk) -lpthread all: $(APP_tool)$(APP_tool): $(SRCS-t)$(CC) $(CFLAGS) $(SRCS-t) -o $ $(LDFLAGS).PHONY: clean
clean:rm $(APP_tool)
测试步骤
先启动进程等待100万定时器插入完成
rootr750-132:/home/ckun/ws/rte_timer# ./timertest -l 1 -n 2 --proc-typeauto
EAL: Detected 32 lcore(s)
EAL: Detected 2 NUMA nodes
EAL: Auto-detected process type: PRIMARY
EAL: Detected shared linkage of DPDK
EAL: Multi-process socket /var/run/dpdk/rte/mp_socket
EAL: Selected IOVA mode PA
EAL: No available hugepages reported in hugepages-1048576kB
EAL: Probing VFIO support...
EAL: VFIO support initialized
EAL: Probe PCI driver: mlx5_pci (15b3:1017) device: 0000:98:00.0 (socket 1)
EAL: Probe PCI driver: mlx5_pci (15b3:1017) device: 0000:98:00.1 (socket 1)
EAL: No legacy callbacks, legacy socket not created
Starting ev_set_timer_worker on core 1
inish set timer on core 1, cost 62.502 这里插入100万个定时器时间与DPDK rte_timer相似
使用perf和FlameGraph生成火焰图
rootr750-132:~/perfs# cat new_svg.sh
#!/bin/bash# 检查是否提供了文件名参数
if [ -z $1 ]; thenecho Usage: $0 filenameexit 1
fifilename$1perf script -i perf.data perf.unfold./stackcollapse-perf.pl perf.unfold perf.folded./flamegraph.pl perf.folded $filenameecho Flamegraph has been saved to $filenamerm -f perf.unfold perf.folded
rootr750-132:~/perfs#
rootr750-132:~/perfs# perf record -e cpu-clock -g -p 2247392
rootr750-132:~/perfs# ./new_svg.sh perf-ev-10-60-1a.svg
Flamegraph has been saved to perf-ev-10-60-1a.svg测试结果记录
超时60秒回调后reset 1秒轮询间隔 10ms event_queue_remove_timeout就占到18%总计libevent花去了20%多的时间。
超时60秒回调后reset 60秒轮询间隔10ms event_queue_remove_timeout 占到0.35% 总计libevent花去 4.2%的时间。
libevent timer 与 DPDK rte_timer 对比
定时器数量超时间隔libevent timerDPDK rte tiemr100万1 秒20%10%100万60秒 0.4%0.42%
在100万定时器单线程处理下在极限1秒的超时情况下rte_timer比 libevent timer性能明显优势。
但是在通常1分钟的超时的情况下两者差距不大。