Python's Archiver

為方便港臺同胞閱覽,Python中國特別推出簡繁體內容轉換功能

xieaotian 发表于 2007-12-25 16:10

Python的速度:文本文件取交

原创:nasi

一个资深工程师曾经跟我说:他对Python很失望。原因就是Python的速度他实在不能忍受。对于一种动态语言,我本来也没有对速度抱有多大的希望。但是,没有试过,并没有数据可以拿来说话。所以接下来我会用一些方法来测试一下Python的速度究竟如何。当然不是单纯的比较,而是放在实际问题下来比较。当然,方法也不保证一定科学,但是会尽量保证公平。对于和Python比较的方法,我会选择开发效率高的解决方案,C语言在200行左右的方案就不加考虑了,而shell/awk这种几行就能解决的方法正是要拿来比较的。因为这些方法正是因为开发效率高,所以很是常用。

这次的实际问题是:有两个文本文件,每个都是10万行,文本文件的大小在100M左右。现在需要知道这两个文件取交有多少行,即是说,有多少行同时在两个文件中存在。这里每个文本文件都经过去重,所以本身没有重复的行。这里待比较的三个方法是shell、awk和python。其中bash和awk的方法是非常常用的,所以我想知道究竟python的速度是怎样的。

评测环境
评测环境是一台Dell D630笔记本,Intel Core2 Duo(1.80GHz)的CPU,内存1G。评测数据是用Python随机生成的文本文件。

shell方法
用shell,一行代码就可以搞定这个需求:

cat uniq.data.1 uniq.data.2 | sort | \
    uniq -c | awk '{if($1==2) c++} END {print c}'
三次测速的结果如下:

9.344s  10.053s  9.751s
平均结果:9.716s

awk方法
下一个方法是用awk来实现,awk的解决方法也很简单:

gawk '{if(ARGIND==1)d[$1]=1; else if($1 in d)c++} END{print c}' \
    uniq.data.1 uniq.data.2
三次测速的结果如下:

2.266s  2.334s  2.349s
平均结果:2.316s

Python方法
Python的方法需要的行数多一些,不过还好只有5行。虽然可以在一行内搞定,只是这样会让程序变慢一点点,所以还是分开来写:

1
2
3
4
5
6
7
data1 = open("uniq.data.1").readlines()
data2 = open("uniq.data.2").readlines()

a = set(data1)
b = set(data2)

print len(a & b)

三次测速的结果如下:

1.235s  1.229s  1.212s
平均结果:1.225s

结论
说实话结果很出乎我意料之外,我没有想到Python居然是最快的方法,比起我们平时经常使用的awk还要快,而且快了近一倍左右。况且Python是这几个方法中最为优雅、最可读的方法,让我对Python的看法有了很大的改观。

xieaotian 发表于 2007-12-25 16:10

python2.4后引入的set类型是C实现的,用的hash算法也很好,至少比sgi stl的hash_set好。
代码还可以写的更短。
a = set(open(”uniq.data.1″))
b = set(open(”uniq.data.2″))

print len(a & b)

直接将文件句柄传给set的话,就可以得到lazy read的好处,更快更省内存。

这个测试只能说明py在文本处理上效率比较好,但在其他方面就不是让人满意了,至少比不上java

页: [1]

Powered by Discuz! Archiver 6.1.0  © 2001-2007 Comsenz Inc.