今天同学说让我写个脚本统计日志。日志是一些ip的捕捉记录,根据协议的类型定义了一些ID和子ID。统计的需求是统计出各个类型的客户IP和服务IP。
这些日志是自动写入的,每天会根据日期生成一个文件夹,文件夹中每个小时生成一个日志文档。脚本要做的就是便利24个文档,读取内容进行分析。
由于需要把24个文档在一起分析,所以同学一开始的思路是:
对每一个类型进行统计,每次统计都遍历所有文件
明显效率不怎么样,但是实际上也够用了因为只要在服务器上让脚本跑起来,过几分钟回去看结果就行了
但是因为脚本要给别人看 = = ,所以不能太难看,因此要重新写一下。
开始的脚本是shell脚本,我不太熟悉,所以用python重写了
思路就是定义一堆 list
变量用来记录 IP
,每读入一个 IP
就在 list
里面查找 not in
,如果找不到就插进去。
最后统计list的长度
这样只需遍历一边文件就行了,但是……………………………………
不知道为啥,貌似python写完之后比原来还慢
后来同学一句话点破,not in 查找的时候需要对字符串进行匹配,而原来的 shell 脚本是用 sort
排序之后用 unique
进行去重统计,难怪这么慢。
于是考虑将 IP
字符串转换成long型再存储在 list
里面,这样匹配的时候是不是能快点?
但是结果好象还是不理想。在少量数据(两个日志文件)的时候,大概能比shell(8s)脚本慢几秒种(16s,是两倍左右),但是在大数据量的情况下就不容乐观了(多出1/3左右的时间)。
大量数据的情况下会慢几分钟 = =
不过貌似数据量越大差距越小,足够大的话有可能超过shell,但是差距还是太差了啊.
后来在网上查找了一下,发现原来字典的查找速度更快,因为字典在查找的时候使用 hash
。于是尝试把所有 list
换成字典。
果然效果神速。在两个文件的时候,2.9秒左右。既然 hash
了,那么将 IP
转化位long型也没有意义了反而做了无用工。去掉之后大概是2.7秒。
然后调整了匹配的顺序,将数量较多的类型先匹配,这样又快了一点点。
如此做一个总结:
- Python 中
list
进行查找和去重的时候(in
操作),使用字符串的匹配,所以速度比较慢。如果存储的是整型则会快一些(数量多的时候还是很慢)。 - 字典使用哈希查找,因此速度很快。
- 调整匹配顺序也可在一定程度上优化速度。