虽然并非您编写的每个Python程序都需要严格的分析,但令人欣慰的是,当问题确实出现时,Python生态系统有多种工具来处理这类问题。分析程序的性能归结为回答四个基本问题:它运行的速度有多快?速度瓶颈在哪里?内存占用是多少?内存泄漏在哪里?使用time进行粗粒度时间计算让我们开始使用一种快速但肮脏的方法来为我们的代码计时:传统的unix时间实用程序。$timepythonyourprogram.pyreal0m1.028suser0m0.001ssys0m0.003s三个输出测量值之间的详细含义在这里stackoverflow文章,但是介绍在这里:real--指实际耗时用户--指外部ofthekernelCPUTimeSpentsys——指的是花费在内核特定功能上的CPU时间。无论系统上运行的其他程序增加的系统时间和用户时间如何,您都可以立即直观地了解您的应用程序用完了多少CPU周期。如果sys和usertime的总和小于realtime,那么你可以猜测大多数程序性能问题很可能与IO等待有关。使用计时上下文管理器进行细粒度计时我们的下一步技术涉及将细粒度计时信息直接写入代码。这是我的时间测量代码的一小段timer.pyimporttimeclassTimer(object):def__init__(self,verbose=False):self.verbose=verbosedef__enter__(self):self.start=time.time()returnselfdef__exit__(self,*args):self.end=time.time()self.secs=self.end-self.startself.msecs=self.secs*1000#millisecsifself.verbose:print'elapsedtime:%fms'%self.msecs要使用它,请使用Python的with关键字和Timer上下文管理器来包装您要计数的代码。当您的代码块开始执行时,它将负责启动计时器,并在您的代码块结束时停止计时器。这个片段示例:fromtimerimportTimerfromredisimportRedisrdb=Redis()withTimer()ast:rdb.lpush("foo","bar")print"=>elaspedlpush:%ss"%t.secswithTimer()ast:rdb.lpop("foo")print"=>elaspedlpop:%ss"%t.secs为了查看我的程序性能随时间变化的趋势,我经常将这些计时器的输出记录到一个文件中。使用探查器逐行计时和分析执行频率RobertKern有一个名为line_profiler的好项目,我经常使用它来分析我的脚本有多快以及每行代码执行的频率:要使用它,您可以使用pip安装它:pipinstallline_profiler安装后,您将获得一个名为line_profiler的新模块和kernprof.py可执行脚本。要使用此工具,首先要在要测量的函数上设置@profile修饰符。别担心,您不需要为此修改器导入任何内容。kernprof.py脚本会在运行时自动注入到您的脚本中。primes.py@profiledefprimes(n):ifn==2:return[2]elifn<2:return[]s=range(3,n+1,2)mroot=n**0.5half=(n+1)/2-1i=0m=3whilem<=mroot:ifs[i]:j=(m*m-3)/2s[j]=0whilej
