Hello,<br><br>To remove bottlenecks I usually instrument some functions in my
application inside a dedicated test and set speed goals there until they are met.
<br>Then I leave the test to avoid speed regressions, when doable, by translating times in pystones.<br><br>
Unless I missed something in the standard library, I feel like there's a missing tool to do it simply:<br>
<br>- the timeit module is nice to try out small code snippets but is not really adapted to manually profile the code of an existing application<br>- the profile module is nice to profile an application as a whole but is not very handy to gather statistics on specific functions in their real execution context<br>
<br>What about adding a decorator that fills a statistics mapping in memory (time+stones), like this:<br><br>>===========<br>import time<br>import sys<br>import logging<br>from test import pystone<br><br>benchtime, stones = pystone.pystones()<br>
<br>def secs_to_kstones(seconds):<br>    return (stones*seconds) / 1000 <br><br>stats = {}<br><br>def reset_stats():<br>    global stats<br>    stats = {}<br><br>def log_stats():<br>    template = '%s : %.2f kstones, %.3f secondes'<br>
    for key, v in stats.items():<br>        logging.debug(template % (key, v['stones'], v['time']))<br><br>if sys.platform == 'win32':<br>    timer = time.clock<br>else:<br>    timer = time.time<br>
<br>def profile(name='stats', stats=stats):<br>    def _profile(function):<br>        def __profile(*args, **kw):<br>            start_time = timer()<br>            try:<br>                return function(*args, **kw)<br>
            finally:<br>                total = timer() - start_time<br>                kstones = secs_to_kstones(total)<br>                stats[name] = {'time': total, <br>                               'stones': kstones} <br>
        return __profile<br>    return _profile<br>>===========<br>
<br>This allows instrumenting the application by decorating some functions, either inside the application, either in a dedicated test:<br><br>>======<br>def my_test():<br>    my.app.slow_stuff = profile('seem slow')(my.app.slow_stuff)<br>
    my.app.other_slow_stuff = profile('seem slow too')(my.app.other_slow_stuff)<br><br>    # should not take more than 40k pystones !   <br>    assert stats['seem slow too']['profile'] < 40<br><br>
    # let's log them<br>    log_stats()<br>>======<br><br><br>Regards,<br>Tarek<br clear="all"><br>-- <br>Tarek Ziadé | Association AfPy | <a href="http://www.afpy.org">www.afpy.org</a><br>Blog FR | <a href="http://programmation-python.org">http://programmation-python.org</a><br>
Blog EN | <a href="http://tarekziade.wordpress.com/">http://tarekziade.wordpress.com/</a>