Skip to content

Latest commit

 

History

History
529 lines (465 loc) · 10.6 KB

201112281806.txt.md

File metadata and controls

529 lines (465 loc) · 10.6 KB

26.6 测试代码性能

http://scz.617.cn/unix/201112281806.txt

A: lotrpy@weibo 2011-12-27 19:07

可以用timeit模块进行快速的性能测试:

python -m timeit -s "x=['a','b','c'];y=['d','e','f']" "[''.join(z) for z in zip(x,y)]"

100000 loops, best of 3: 2.24 usec per loop

A: scz@nsfocus

python MergeListProfile.py


#!/usr/bin/env python

-- encoding: utf-8 --

进行性能对比测试。

从Python Cookbook第1版"1.9 Finding the Intersection of Two Dictionaries"

小节扒出来的代码,很有借鉴意义,用于测试各种函数的性能,直观显示对比结果。

入门必备技能!

import time import sys from itertools import izip

##########################################################################

返回值是浮点数,以s为单位。注意,循环了100000次,时间放大了100000倍。

def TimeOfFunction ( function, num=100000 ):

def void() :
    pass
#
# end of void
#

time_a  = time.clock()
for i in range( num ) :
    void()
#
# end of for
#
time_b  = time.clock()

time_c  = time.clock()
for i in range( num ) :
    function()
#
# end of function
#
time_d  = time.clock()

#
# 返回函数名以及执行时间,已经考虑了调度时间。
#
return( function.__name__, ( time_d - time_c ) - ( time_b - time_a ) )

end of TimeOfFunction

##########################################################################

"""

如果用这组x、y进行测试,应该TimeOfFunction( function, num=1000000 )。此

时TargetFunc_7()只排第2。

x = ['a','b','c'] y = ['d','e','f'] """

如果用这组x、y进行测试,应该TimeOfFunction( function, num=100000 )。此时

TargetFunc_7()最快。看上去,大数据量时更应该使用izip()。

x = ['A' + str(i) for i in xrange(0,100)] y = ['B' + str(i) for i in xrange(0,100)]

##########################################################################

不同的实现方式。

from scz

def TargetFunc_0 () : return( map((lambda x,y:x+y),x,y) )

end of TargetFunc_0

from lotrpy@weibo

def TargetFunc_1 () : return( [''.join(z) for z in zip(x,y)] )

end of TargetFunc_1

normal

def TargetFunc_2 () : ret = [] n = len( x ) for i in range( n ) : ret.append( x[i] + y[i] ) # # end of for # return( ret )

end of TargetFunc_2

from hume

def TargetFunc_3 () : return( [v+y[i] for i,v in enumerate(x)] )

end of TargetFunc_3

from lzx@nsfocus

def TargetFunc_4 () : return( [x[i]+y[i] for i in range(len(x))] )

end of TargetFunc_4

from zyh@nsfocus

def TargetFunc_5 () : return( [i+j for i,j in zip(x,y)] )

end of TargetFunc_5

from 请叫我李牛牛@weibo

def TargetFunc_6 () : L = len( x ) # # range()会直接生成一个list,xrange()则不会,而是每次被调用时返回其中 # 的一个值,xrange()在循环中的性能比range()好,尤其是返回很大的list时, # 尽量用xrange()。 # return( [x[i]+y[i] for i in xrange(L)] )

end of TargetFunc_6

from hw@nsfocus

def TargetFunc_7 () : return( [i+j for i,j in izip(x,y)] )

end of TargetFunc_7

##########################################################################

测试不同的TargetFunc_n()函数性能

ret = {} funcs =
[ TargetFunc_0, TargetFunc_1, TargetFunc_2, TargetFunc_3, TargetFunc_4, TargetFunc_5, TargetFunc_6, TargetFunc_7 ]

确保这些函数返回值一致。

oldret = [] newret = [] for function in funcs : newret = function() if not oldret : # # 这里不需要动用copy.copy()或copy.deepcopy() # oldret = newret elif oldret != newret : print 'Checking %s()' % function.name sys.exit( -1 )

end of for

循环10次计算平均值

num = 10 for i in range( num ) : # print "Round[%u]" % i # for function in funcs : a, b = TimeOfFunction( function ) if a in ret : ret[a] += b else : ret[a] = b print "%s : %.9fs" % ( a, b ) # # end of for #

end of for

print 'Average:'

2010-12-17 15:18 scz

对各函数运行时间进行降序排序并输出。map()第一形参是None时相当于zip()。

result = zip( ret.values(), ret.keys() )

出于空间上的考虑,sort()直接在原list所在空间上进行排序,就是说调用结束后

result被改变。sort()不会返回新的list。

result.sort( reverse=True ) for x in result : print "%s : %.9fs" % ( x[1], x[0] / num )

end of for


假设:

x = ['a','b','c'] y = ['d','e','f'] num = 1000000

Average: TargetFunc_2 : 2.313999329s TargetFunc_1 : 2.298966419s TargetFunc_0 : 2.185276983s TargetFunc_5 : 2.009906884s TargetFunc_4 : 1.765377419s TargetFunc_3 : 1.676222731s TargetFunc_7 : 1.586907511s TargetFunc_6 : 1.529695776s

假设:

x = ['A' + str(i) for i in xrange(0,100)] y = ['B' + str(i) for i in xrange(0,100)] num = 100000

Average: TargetFunc_1 : 3.966280626s TargetFunc_2 : 3.902535827s TargetFunc_0 : 3.218697966s TargetFunc_5 : 2.759791314s TargetFunc_3 : 2.592151199s TargetFunc_4 : 2.578258690s TargetFunc_6 : 2.572227805s TargetFunc_7 : 2.149801880s

当x、y是大list时,izip()效率优势明显,比enumerate()、xrange()都快。

A: hw@nsfocus 2012-01-09 15:10

python MergeListProfileOther.py


#!/usr/bin/env python

-- encoding: utf-8 --

hw@nsfocus 2012-01-09 15:10

进行性能对比测试。

import sys import timeit from itertools import izip

##########################################################################

返回值是浮点数,以s为单位。注意,循环了100000次,时间放大了100000倍。

def TimeOfFunction ( fname, num=100000 ): t = timeit.Timer( '%s()' % fname, 'from main import %s' % fname ) # # 返回函数名以及执行时间。 # return( fname, t.timeit( number=num ) )

end of TimeOfFunction

##########################################################################

"""

如果用这组x、y进行测试,应该TimeOfFunction( function, num=1000000 )。此

时TargetFunc_7()只排第2。

x = ['a','b','c'] y = ['d','e','f'] """

如果用这组x、y进行测试,应该TimeOfFunction( function, num=100000 )。此时

TargetFunc_7()最快。看上去,大数据量时更应该使用izip()。

x = ['A' + str(i) for i in xrange(0,100)] y = ['B' + str(i) for i in xrange(0,100)]

##########################################################################

不同的实现方式。

from scz

def TargetFunc_0 () : return( map((lambda x,y:x+y),x,y) )

end of TargetFunc_0

from lotrpy@weibo

def TargetFunc_1 () : return( [''.join(z) for z in zip(x,y)] )

end of TargetFunc_1

normal

def TargetFunc_2 () : ret = [] n = len( x ) for i in range( n ) : ret.append( x[i] + y[i] ) # # end of for # return( ret )

end of TargetFunc_2

from hume

def TargetFunc_3 () : return( [v+y[i] for i,v in enumerate(x)] )

end of TargetFunc_3

from lzx@nsfocus

def TargetFunc_4 () : return( [x[i]+y[i] for i in range(len(x))] )

end of TargetFunc_4

from zyh@nsfocus

def TargetFunc_5 () : return( [i+j for i,j in zip(x,y)] )

end of TargetFunc_5

from 请叫我李牛牛@weibo

def TargetFunc_6 () : L = len( x ) # # range()会直接生成一个list,xrange()则不会,而是每次被调用时返回其中 # 的一个值,xrange()在循环中的性能比range()好,尤其是返回很大的list时, # 尽量用xrange()。 # return( [x[i]+y[i] for i in xrange(L)] )

end of TargetFunc_6

from hw@nsfocus

def TargetFunc_7 () : return( [i+j for i,j in izip(x,y)] )

end of TargetFunc_7

##########################################################################

测试不同的TargetFunc_n()函数性能

if 'main' == name : this = sys.modules['main'] # # 确保这些函数返回值一致。 # oldret = [] newret = [] for f in dir( this ) : if callable( getattr( this, f, None ) ) and f.startswith( 'TargetFunc_' ) : newret = eval( '%s()' % f ) if not oldret : # # 这里不需要动用copy.copy()或copy.deepcopy() # oldret = newret elif oldret != newret : print 'Checking %s()' % f sys.exit( -1 ) # # end of for # ret = {} # # 循环10次计算平均值 # num = 10 for i in range( num ) : # print "Round[%u]" % i # for f in dir( this ) : if callable( getattr( this, f, None ) ) and f.startswith( 'TargetFunc_' ) : a, b = TimeOfFunction( f ) if a in ret : ret[a] += b else : ret[a] = b print "%s : %.9fs" % ( a, b ) # # end of for # # # end of for # print 'Average:' # # 2010-12-17 15:18 scz # # 对各函数运行时间进行降序排序并输出。map()第一形参是None时相当于zip()。 # result = zip( ret.values(), ret.keys() ) # # 出于空间上的考虑,sort()直接在原list所在空间上进行排序,就是说调用结束后 # result被改变。sort()不会返回新的list。 # result.sort( reverse=True ) for x in result : print "%s : %.9fs" % ( x[1], x[0] / num ) # # end of for #

假设:

x = ['A' + str(i) for i in xrange(0,100)] y = ['B' + str(i) for i in xrange(0,100)] num = 100000

Average: TargetFunc_1 : 3.931241167s TargetFunc_2 : 3.912196821s TargetFunc_0 : 3.108840062s TargetFunc_5 : 2.775525899s TargetFunc_3 : 2.744446860s TargetFunc_4 : 2.742812149s TargetFunc_6 : 2.646931505s TargetFunc_7 : 2.190302298s

MergeListProfile.py的TimeOfFunction()是自己实现的,MergeListProfileOther.py 的TimeOfFunction()用了timeit模块。从最终结果看,自己实现的TimeOfFunction() 相比timeit模块,没有额外的效率损耗,两种办法都可以用。