最近股票做的不错,实在闲,就想着把日志分析这一块再深入一下。
顺便自己写了几个版本的异步Syslog服务器,用了几种模型,往往是弄完以后呢,看网上评测有更佳实现,或者有更好玩的东西,所以两个语言的多个版本就全弄出来了。
但是异步这事我以前用的比较少,对性能没有太大概念,今天做了个不太严谨的对比测试。
几套程序的流程完全一致,接收日志(udp,rfc3164),然后分解为对应的字段,最后写入mysql库(其实是mariadb)
但是结果与我预期的完全不同,甚至可以说跌掉下巴。
环境呢,本机,13代i5,32G内存,几个m2没做阵列,几个ssd的sata做了阵列但没用到,数据收发都在本机
系统 win10专业版
python 3.11.7
.net framework 4.5 / 4.5.2 / 4.8
.net 8.0
框架 | mysql连接方式 | 完成数量 | 内存占用 |
gevent | 直连 | 全部 | 30M |
gevent | 连接池 | 99.8%以上 | 29 - 450 - 75M |
asyncio | 直连 | 全部 | 23M |
asyncio | 连接池 | 40xxx (80%) | 23M |
.net framework | 直连 | 1500+ | 63M |
.net framework | 连接池 | 100 | 63M |
测试是python脚本异步方式直接丢50000个日志记录过来。目测呢,大概每秒钟接近2000个记录。这个频率应该比超大型网站也不差了。
其中.net分别测试了.net framework 4.5/4.5.2/4.8,结果都一样
gevent+连接池因为内存占用太过于夸张,当然工作完成后会回落到70多M,但是一旦遇到突发事件,这个内存占用情况还是挺凶的的,所以感觉不太好。
cpu的使用率没有记录,因为我这关掉e核以后呢,从cpu使用来看,这几个都会占满一个核心,asyncio的使用会少一些,占不满一个核心。
所以最终我打算选择asyncio + 单连接的形式。因为不论压力有多大,内存和cpu使用情况都很稳定,内存从没有超过24M的情况,而且数据一条没丢,这个挺6的。
而.net这个,远超想象,连接池我反复调整都没用,一旦达到官方控件的极限就崩了,而官方还特意讲明应该让系统自己调节连接池,可就是这么个结果……还不如他自己明确禁止的单连接形式。测试了很多轮,最多处理1500多条,有点开玩笑。
而且很奇怪啊,这几个都是用的mysql官方控件,池的上限也曾经调到最大了,但结果是一样的。感觉python和.net的官方mysql控件全都挺差的,只要用连接池,就要么崩掉,要么大量丢数据。也难怪有那么几个比较大的python项目都不推荐用官方控件……
总之,个人认为,gevent和asyncio没太大区别,可能在某些特定情况是不同的,但在我的应用场景来说,几M的内存不是事。
然后呢,mysql官方出的连接控件是很烂的,.net平台和python都是。如果要用官方控件,则直连形式是最好的,连接池模式要显式关闭,否则莫名其妙丢数据就会很难调试,因为我这各个平台都没有任何报错。
大家可以做个参考吧,从我这里的情况来看,用gevent和asyncio都是很好的,资源使用很少,效率高,且数据一条不丢,gevent编程还很方便。至于.net,那就算了吧。
===============
之所以说跌掉下巴,是测试之前按常理推测,我估计.net能完爆python,因为一个是编译,一个是脚本;一个是多线程,一个是单线程。真是没想到是这么个结果……
================
后续
隔了几天想想不服气,又用queue试了一下,.net 8.0+vs2022,依然掉渣。用官方提供的异步udp服务器代码,收到数据以后异步塞到一个queue里面,不做其他处理,依然只能完成70%左右,而且接收速度明显比python版本的慢一些。
.net真是开玩笑,彻底放弃了。