Contents

日志统计脚本

Contents

今天同学说让我写个脚本统计日志。日志是一些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秒。
然后调整了匹配的顺序,将数量较多的类型先匹配,这样又快了一点点。
如此做一个总结:

  1. Python 中 list 进行查找和去重的时候(in 操作),使用字符串的匹配,所以速度比较慢。如果存储的是整型则会快一些(数量多的时候还是很慢)。
  2. 字典使用哈希查找,因此速度很快。
  3. 调整匹配顺序也可在一定程度上优化速度。