はじめに
現在、研究でApacheログの解析をしています。apache-log-parserというモジュールを使用していたのですが、ふと、このモジュール使う必要あるのかと疑問に思って調べてみました。
それは、IPアドレスのパースをしたら正規表現を使用した方法とモジュールを使用した方法どちらが早いか??ということです。
対象
1日分のログ(約45MB、184087行)です。今回は、IPアドレスのみ表示します。
正規表現
まずは、正規表現による方法です。
sample_regex.py
# coding:utf-8
# 正規表現とモジュールでIPアドレス検索はどっちが早いか確かめるプログラム
import time
import sys
import re
if __name__ == "__main__":
start = time.time()
argvs = sys.argv
f = open("~/apache_log_analysis/log_data/" + argvs[1])
re_ip_addr = re.compile("((?:(?:25[0-5]|2[0-4][0-9]|[01]?[0-9][0-9]?)\.){3}(?:25[0-5]|2[0-4][0-9]|[01]?[0-9][0-9]?))")
for line in f.readlines():
try:
ip_addr = re_ip_addr.search(line)
if ip_addr.group() is not None:
print ip_addr.group()
except:
print "logfiled turned over"
f.close()
elapsed_time = time.time() - start
print ("elapsed_time:{0}".format(elapsed_time)) + "[sec]"
print "exit"
結果は、2.10073304176[sec]でした!何回かやったら約0.9[sec]が最速のようで、実行結果のほとんどで0.9[sec]が計測されました。
モジュール使用
次に、モジュールを使用した方法です。
sample_module.py
# coding:utf-8
# 正規表現とモジュールでIPアドレス検索はどっちが早いか確かめるプログラム
import time
import sys
import apache_log_parser
if __name__ == "__main__":
start = time.time()
argvs = sys.argv
f = open("~/apache_log_analysis/log_data/" + argvs[1])
parser = apache_log_parser.make_parser('%h %l %u %t \"%r\" %>s %b \"%{Referer}i\" \"%{User-Agent}i\"')
for line in f.readlines():
try:
log_data = parser(line)
print log_data['remote_host']
except:
print "logfiled turned over"
f.close()
elapsed_time = time.time() - start
print ("elapsed_time:{0}".format(elapsed_time)) + "[sec]"
print "exit"
結果は、78.4286789894[sec]でした!あまりの遅さにプログラム間違えたか何回も確認してなんなんだこいつって思うぐらいでした。
おわりに
考えてみればモジュール使用だと他に色んな情報もパースしちゃうから当然の結果でしたね。それにしても遅すぎてびっくりしました。
モジュールのソースを見たら、幅広く対応できるように作ってあったので、なるほどって感じでした。
今後は、モジュールに頼りすぎないで、自前で実装したほうが早いところはモジュールのソースから引っ張って必要なところだけ使わせてもらったりしたほうが良いのかもな〜って思いました。
便利だけどそれに頼りすぎてもダメだということを学べました。。