-
Notifications
You must be signed in to change notification settings - Fork 434
Performance Notes
The markdown2 sources have a perf
sub-directory with some performance tools
for profiling markdown2 and comparing its speed against markdown.py and
Markdown.pl.
There are two sets of "suites" (sets of .text files to convert) that I've been
using for testing. One is a copy of all the test cases from the test
dir (see
Testing Notes). The second is a .text file for every description and comment
in the Python Cookbook. To generate the performance suites run:
cd perf
python gen_perf_cases.py
I'd be very interested in other real-world performance suites. Please log an issue if you have a suggestion for another perf suite that I should check.
WARNING: markdown.py
has gone through some significant work since I ran these numbers. I haven't followed the recent markdown.py
work and haven't re-run the perf suite yet.
Currently I compare the processing time against
Markdown.pl and
markdown.py. I'd
like to compare against markdown.php but I'd appreciate someone's help on doing for markdown.php
what perf/Markdown.pm and
perf/time_markdown_pl.pl are for Markdown.pl
(basically tweaking it to be
runnable from the command line).
Of course, as with all performance comparisons, only the relative numbers are important. These timings were done on a MacBook (1.82 Ghz Intel Core 2 Duo) running Mac OS X 10.4.10 with Python 2.5.1:
$ python perf.py -r 10 tmp-test-cases
Time conversion of tmp-test-cases/*.text (plat=darwin):
Markdown.pl: best of 10: 0.372s
markdown.py: best of 10: 0.295s
markdown2.py: best of 10: 0.221s
$ python perf.py tmp-aspn-cases
Time conversion of tmp-aspn-cases/*.text (plat=darwin):
Markdown.pl: best of 3: 5.842s
We've got a problem header!
We've got a problem header!
We've got a problem header!
We've got a problem header!
We've got a problem header!
We've got a problem header!
markdown.py: best of 3: 18.920s
markdown2.py: best of 3: 4.956s
The "We've got a problem header!" are warnings spit out by markdown.py
for
syntax that it cannot handle in some of the ASPN test cases.
Here is profiling information for markdown2.py
to show where the best
possible performance gains could be found. However, I'm content with the
current performance -- at least with the current perf suites. The profiling is
done with Python 2.5's hotshot module.
$ python perf.py --hotshot -i markdown2.py --repeat 5 tmp-test-cases
Profile conversion of tmp-test-cases/*.text (plat=darwin):
markdown2.py: best of 5: 0.233s
79855 function calls (77872 primitive calls) in 1.246 CPU seconds
Ordered by: internal time, call count
List reduced from 167 to 20 due to restriction <20>
ncalls tottime percall cumtime percall filename:lineno(function)
950 0.257 0.000 0.258 0.000 markdown2.py:159(_detab)
745 0.189 0.000 0.207 0.000 markdown2.py:212(_hash_html_blocks)
4270 0.078 0.000 0.078 0.000 markdown2.py:880(_encode_backslash_escapes)
2700 0.058 0.000 0.079 0.000 markdown2.py:800(_do_italics_and_bold)
465 0.045 0.000 0.065 0.000 markdown2.py:567(_do_headers)
860/325 0.044 0.000 0.150 0.000 markdown2.py:596(_do_lists)
465/420 0.040 0.000 0.055 0.000 markdown2.py:839(_do_block_quotes)
465/280 0.039 0.000 0.779 0.003 markdown2.py:292(_run_block_gamut)
290 0.034 0.000 0.034 0.000 markdown2.py:930(_unescape_special_chars)
2700 0.033 0.000 0.344 0.000 markdown2.py:319(_run_span_gamut)
2700 0.032 0.000 0.033 0.000 markdown2.py:904(_do_auto_links)
2700 0.029 0.000 0.029 0.000 markdown2.py:415(_do_links)
2700 0.025 0.000 0.103 0.000 markdown2.py:362(_escape_special_chars)
465 0.023 0.000 0.049 0.000 markdown2.py:716(_do_code_blocks)
3040 0.021 0.000 0.029 0.000 re.py:136(sub)
5139 0.020 0.000 0.076 0.000 re.py:219(_compile)
2700 0.018 0.000 0.025 0.000 markdown2.py:746(_do_code_spans)
1 0.018 0.018 1.246 1.246 perf.py:59(time_markdown2_py)
2835 0.018 0.000 0.018 0.000 markdown2.py:871(_encode_amps_and_angles)
465 0.016 0.000 0.303 0.001 markdown2.py:845(_form_paragraphs)
$ python perf.py --hotshot -i markdown2.py tmp-aspn-cases
Profile conversion of tmp-aspn-cases/*.text (plat=darwin):
markdown2.py: best of 1: 5.317s
359188 function calls (357235 primitive calls) in 5.377 CPU seconds
Ordered by: internal time, call count
List reduced from 166 to 20 due to restriction <20>
ncalls tottime percall cumtime percall filename:lineno(function)
6161 0.446 0.000 0.464 0.000 markdown2.py:567(_do_headers)
6200/6020 0.372 0.000 0.486 0.000 markdown2.py:596(_do_lists)
1 0.365 0.365 5.377 5.377 perf.py:59(time_markdown2_py)
11373 0.358 0.000 0.474 0.000 markdown2.py:800(_do_italics_and_bold)
6161/5756 0.355 0.000 3.960 0.001 markdown2.py:292(_run_block_gamut)
11635 0.302 0.000 0.302 0.000 markdown2.py:880(_encode_backslash_escapes)
5757 0.287 0.000 0.287 0.000 markdown2.py:930(_unescape_special_chars)
6161/5897 0.246 0.000 0.311 0.000 markdown2.py:839(_do_block_quotes)
6161 0.212 0.000 0.377 0.000 markdown2.py:716(_do_code_blocks)
7852 0.211 0.000 0.213 0.000 markdown2.py:159(_detab)
11373 0.203 0.000 0.203 0.000 markdown2.py:904(_do_auto_links)
11917 0.185 0.000 0.220 0.000 markdown2.py:212(_hash_html_blocks)
41701 0.182 0.000 0.239 0.000 re.py:219(_compile)
5756 0.156 0.000 4.899 0.001 markdown2.py:114(convert)
17394 0.153 0.000 0.199 0.000 re.py:136(sub)
5756 0.144 0.000 0.198 0.000 markdown2.py:252(_strip_link_definitions)
11373 0.140 0.000 1.668 0.000 markdown2.py:319(_run_span_gamut)
11373 0.127 0.000 0.128 0.000 markdown2.py:746(_do_code_spans)
11373 0.107 0.000 0.107 0.000 markdown2.py:871(_encode_amps_and_angles)
6161 0.102 0.000 0.117 0.000 re.py:154(split)
Here is some profiling info for markdown.py, in case that might be useful for that implementor:
$ python perf.py --hotshot -i markdown.py --repeat 5 tmp-test-cases
Profile conversion of tmp-test-cases/*.text (plat=darwin):
markdown.py: best of 5: 0.350s
327998 function calls (302997 primitive calls) in 1.821 CPU seconds
Ordered by: internal time, call count
List reduced from 167 to 20 due to restriction <20>
ncalls tottime percall cumtime percall filename:lineno(function)
88325/77920 0.632 0.000 0.719 0.000 markdown.py:1530(_applyPattern)
3615/3070 0.278 0.000 0.983 0.000 markdown.py:1480(_handleInlineWrapper)
11100 0.129 0.000 0.129 0.000 markdown.py:451(_isLine)
6870/485 0.114 0.000 1.225 0.003 markdown.py:1213(_processSection)
6140/270 0.080 0.000 0.204 0.001 markdown.py:281(toxml)
280 0.067 0.000 1.739 0.006 markdown.py:1599(convert)
7925 0.051 0.000 0.051 0.000 markdown.py:183(normalizeEntities)
7165 0.040 0.000 0.100 0.000 markdown.py:357(toxml)
88325 0.029 0.000 0.029 0.000 markdown.py:689(getCompiledRegExp)
270 0.027 0.000 1.465 0.005 markdown.py:1161(_transform)
690 0.025 0.000 0.033 0.000 markdown.py:915(_findHead)
7730 0.021 0.000 0.025 0.000 markdown.py:165(createTextNode)
6140 0.021 0.000 0.037 0.000 markdown.py:158(createElement)
1 0.020 0.020 1.821 1.821 perf.py:34(time_markdown_py)
270 0.020 0.000 0.020 0.000 markdown.py:414(run)
270 0.020 0.000 0.020 0.000 markdown.py:581(run)
4380 0.019 0.000 0.027 0.000 markdown.py:1410(_linesUntil)
7185 0.018 0.000 0.018 0.000 markdown.py:354(handleAttributes)
6140 0.016 0.000 0.016 0.000 markdown.py:219(__init__)
270 0.015 0.000 0.019 0.000 markdown.py:508(run)
$ python perf.py --hotshot -i markdown.py tmp-aspn-cases
Profile conversion of tmp-aspn-cases/*.text (plat=darwin):
We've got a problem header!
We've got a problem header!
markdown.py: best of 1: 21.303s
1464504 function calls (1323926 primitive calls) in 21.359 CPU seconds
Ordered by: internal time, call count
List reduced from 164 to 20 due to restriction <20>
ncalls tottime percall cumtime percall filename:lineno(function)
350801/263536 15.007 0.000 16.187 0.000 markdown.py:1530(_applyPattern)
15884/11305 1.084 0.000 17.072 0.002 markdown.py:1480(_handleInlineWrapper)
61479 0.896 0.000 0.896 0.000 markdown.py:451(_isLine)
350801 0.825 0.000 0.825 0.000 markdown.py:689(getCompiledRegExp)
32038/5880 0.449 0.000 17.946 0.003 markdown.py:1213(_processSection)
1 0.387 0.387 21.359 21.359 perf.py:34(time_markdown_py)
26431/5737 0.357 0.000 1.022 0.000 markdown.py:281(toxml)
43395 0.293 0.000 0.293 0.000 markdown.py:183(normalizeEntities)
5737 0.281 0.000 19.691 0.003 markdown.py:1161(_transform)
37647 0.192 0.000 0.525 0.000 markdown.py:357(toxml)
5737 0.118 0.000 0.118 0.000 markdown.py:581(run)
5737 0.114 0.000 0.114 0.000 markdown.py:414(run)
5737 0.105 0.000 0.107 0.000 markdown.py:508(run)
37647 0.101 0.000 0.101 0.000 markdown.py:354(handleAttributes)
42226 0.100 0.000 0.120 0.000 markdown.py:165(createTextNode)
2075 0.086 0.000 0.143 0.000 markdown.py:915(_findHead)
5737 0.084 0.000 0.980 0.000 markdown.py:445(run)
22822 0.075 0.000 0.107 0.000 markdown.py:1410(_linesUntil)
26431 0.075 0.000 0.075 0.000 markdown.py:219(__init__)
5756 0.073 0.000 20.827 0.004 markdown.py:1599(convert)