26.6 测试代码性能 https://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模块,没有额外的效率损耗,两种办法都可以用。