上篇提到,我在搞个金融市场分析平台。

 

不可避免的,肯定需要脚本语言环境来实现一些功能,比如用户自行编写复杂逻辑。

花了几天时间,用几种语言都试了一下,差距之大,不说毁三观,至少我是没想到能差这么多。

 

前提:数据相同,数据库相同,分析逻辑完全相同(甚至几乎做到跨语言实现语法接近完全相同),操作系统相同,硬件相同。

数据量:36个品种,11个周期,也就是说每一轮都进行396次全量扫描,每一次使用的k线数量在3.5到5万之间,上限5万,指标数量与k线相同,上限5万,但是有3条指标线,所以上限是15万。那么数据量就是5万k线,然后由5万k线计算出15万指标线,总数量上限20万。因为每个周期的数据量并不同,所以这里只说上限。那么每一轮都扫描396*20万=7920万上限的数据。同时有些数据是由基础数据聚合而成,这里面的聚合逻辑完全相同,就按照8000万来概算吧。

 

猜猜各语言的性能表现是怎样的?

 

首先最差的,python 3.13,执行时间83.94秒,内存使用量400多m,我都懒得去细看了,重复运行了几次,看着数据没什么差别,就直接关了。。。

然后go+lua+预编译,执行时间52.26秒,内存 144到210m之间。

rust+rhai,执行时间9.24秒,内存80到86m左右。

rust+rhai+预编译,执行时间6.4秒,内存80到85m左右。

 

python这个就没什么好说的了,这个内存使用量和效率来说,只能自己玩,只适合验证想法。

go这个,我已尽全力优化了,而且这个在逻辑上还做了优化,遍历逻辑是由go来做的,指标计算由go来提供,还给lua做了预编译以后的复用,可以说这是优化到极致了。怎么说呢,任何语言与lua进行嫁接的话,都必须要经过中间层的数据类型转换,数据传递这些,这是个无法避免的事情,所以大数据量的场景,其实lua的方案是不太行的。

最后的rust,其实写这篇日记的时候已经优化到5.12秒了,不论性能还是内存使用,这是真强到没朋友了。。。而且运行逻辑来说,rust这边是吃亏的,甚至有些调试的代码我都没删,同时为了贴近最终形态,有许多东西我都是用脚本写的,而不是由rust提供计算功能和执行遍历逻辑。如果要确保完全相同逻辑与rust提供计算的话,还可以提升不少。。。这个方案的强项在于rust和rhai之间数据传递是零拷贝,特别是大数据量的时候,与其他方案的性能差距会显著扩大;以及rhai与rust的底层数据类型是相同的,所以数据类型的校验成本接近0

 

网上都说lua的性能接近c,从我这实测来说,我感觉这差的有点多。。。而且lua与其他语言交互的话,必须通过中间的c层中转,这是个无法解决的问题。

这些事还是要自己测试才行啊,不能听网上无脑瞎吹。

 


再补充一个数据,串行非并行,经过逻辑方面优化,扫描整个a股市场5182个品种,两周期,数据上限一万(实际可用数据平均5500到6000之间),结合自己的逻辑,每一轮数据量大概15万,总计分析数据量大概15.546亿,耗时340.5秒,内存88到90m之间,无波动,很硬核。


后续,继续优化与劣化。。。

在增加了所有安全性检查和校验以后,rhai方案的性能降低了一倍,目前在1.4秒以内。说降低一倍,是因为如果删掉这些辅助校验,已经稳稳的压到650ms了。

能从5秒多压到650ms,提升了接近10倍性能,是用了内存和结构映射,也就是说,其实这种程序,最大的性能瓶颈在大量数据传递,尤其是和lua这种“域外”的进行数据传递,还有就是这种场景下的数据类型转换。那么也就是说,只要能在这个环节提升性能,就可以指数级提升项目整体性能。我也曾想过内存映射给lua,但是这个情况有点极端,因为一方面,跨语言这么干,风险贼大,一不小心就把操作系统干废了,另一方面lua是有文件系统访问能力的,而计划中会运行别人的脚本,所以即便用lua也绝不会做这样的功能优化,因为风险太高,而如果是自己用的话,我凭什么要给自己找麻烦用个lua啊?直接rhai不就得了。。。

那么最终,在我力所能及的优化以后,成绩大概是这样的:

总分析数据量:15.5亿以上,并且要计算一轮常用指标(macd)

python : 84秒,内存400M以上

go+lua+预编译:52秒,内存140到210M之间

rust+rhai:9.24秒,内存80到86M

rust+rhai+预编译:650ms(0.65秒),内存80到85M

作者 听涛

发表回复

您的邮箱地址不会被公开。 必填项已用 * 标注