日志统计脚本
今天同学说让我写个脚本统计日志。日志是一些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
操作),使用字符串的匹配,所以速度比较慢。如果存储的是整型则会快一些(数量多的时候还是很慢)。 - 字典使用哈希查找,因此速度很快。
- 调整匹配顺序也可在一定程度上优化速度。