par模块性能调优记录

uliweb的文档是使用markdown记录的,因此我使用了自已写的par和parm两个包将其转为html格式。其中par是用来转換markdown为html文本,而parm则对par进行了包装,可以生成目录等结构。但是最近发现在转換html时,速度比较慢,特别是在转orm文档时,时间非常长,感觉性能有问题。因为以前好象没这么慢。于是打算看一看有什么问题,如何进行优化。

为了进行性能调优,我想到的是使用profile。曾经以前弄过,时间长都忘了。因此我搜索了一下相关的文档,找到几篇:Python Profile 工具性能分析,它介绍了如何使用cProfile。摘录如下:

python -m cProfile -o test1.out test1.py

使用上面的命令对test1.py执行后生成profile文件。生成之后,profile文件是二进制的,需要特殊工具来查看,可以使用:

python -c "import pstats; p=pstats.Stats('test1.out'); p.sort_stats('time').print_stats()"

只要把上面的 test1.out 改为实际的文件名即可。主要看的项是:ncalls 和 tottime。一个表示调用次数,一个表示在当前函数执行的时间,不包括调用其中的子函数的时间。

在par的examples下有一个md2html.py,它其实是一个测试程序,其中有一段很长的markdown的语法介绍文本,不过平时我是将其给替換掉了。于是为了测试,将其改回来,这样测试的文本就足够长了。

经测试结果如下:

ncalls  tottime  percall  cumtime  percall filename:lineno(function)
153751    4.921    0.000    4.921    0.000 {repr}
322631/187    3.521    0.000   10.362    0.055 ..\par\pyPEG.py:143(parseLine)
334595    0.384    0.000    0.520    0.000 c:\Python27\lib\re.py:226(_compile)
165414    0.206    0.000    0.206    0.000 {method 'match' of '_sre.SRE_Pattern' objects}

可以看到 repr 耗时特别长。但是这个repr是内置的函数,也看不出谁在调用。而pyPEG.py中的parseLine执行了32万多次,时间也很长。估计是在这个函数中有问题。

我又查询了另一篇文章 Python性能分析指南 ,在这篇文章中讲了一个模块是 line-profile,它可以在某个函数上显示每一行执行的profile结果。于是我通过pip进行了安装。不过安装这个包需要C编译器。因为我以前装过cython,所以配置了mingw环境,所以到是在windows下安装没什么问题。这个包可能在linux下安装会更方便些。安装后,在python的Scripts目录下会有一个叫 kernprof.py 的工具。为了使用line-profile,需要先修改源码,在需要监控的函数上添加 @profile 。于是我修改了pyPEG.py源文件,在parseLine上添加了 @profile 方法(注意pyPEG有一个是类方法,一个是普通方法,要加在类方法上)。然后在命令行执行:

kernprof.py -l -v md2html.py 2> b.txt

上面 -l 表示按行来处理,-v 表示执行后显示结果, 2>b.txt 是为了将出错信息重定向到一个文件中。我在执行中会显示很多错误,好象也不影响运行。不过因为代码运行次数太多,如果不重定向会输出大量的信息,非常慢。查看上面的输出结果我看到在第250行:

syntaxError(pattern.pattern+' text='+repr(text))

花时时间占总时间的13.6。原来这里有一个repr。

但是我就有一个疑问,这里不是会抛异常吗?怎么会执行那么多次。原来在parseLine的处理中,它其实是一个递归调用,当抛出异常时,它会捕获异常,并丢弃。所以这里只有最外层的可能会输出,中间的出错信息其实是无用的。因此我将所有syntaxError的参数都去掉了。再执行,由原来的10秒左右降到了2秒左右,性能大为提高。

在其间,我还试了使用cython将pyPEG.py转为pyPEG.pyx,然后编译为pyd,但是在没有解决真正的问题时,的确快了一点,但是效果不是很明显。因为我只是简单地编译了一下,也没有处理返回值,类型之类的,所以不明显。

你可能感兴趣的:(par模块性能调优记录)