sergzach
sergzach

Reputation: 6754

cProfiler: How to get stat by execution order?

I'd like to get stat of profiler ordered and grouped not by number of calls and not by time spent but by natural execution order.

For example, if we use cProfiler for the next simple program:

def my_sleep0():
    sleep( 0.05 )

def my_sleep1():
    sleep( 0.15 )
    my_sleep2()

def my_sleep2():
    my_sleep3()

def my_sleep3():
    sleep( 0.1 )


if __name__ == '__main__':

    p = Profiler( './' ) # a wrapper for cProfiler, cProfiler starts here

    i = 10

    for i in range( 1, 5 ):
        i += 100
        my_sleep0()
        my_sleep1()
        my_sleep1()

    # cProfiler destructs and ends here

I want a stat by natural execution order, for example:

Ordered by: execution

calling_function    cumtime backtrace

test.py:36(my_sleep0)   <cumtime>  test.py:43()
test.py:39(my_sleep1)   <cumtime>  test.py:44()
test.py:43(my_sleep2)   <cumtime>  test.py:20 called by test.py:44(my_sleep1)
test.py:43(my_sleep3)   <cumtime>  test.py:25 called by test.py:20(my_sleep1)->test.py:26(my_sleep2)
test.py:39(my_sleep1)   <cumtime>  test.py:45()
test.py:43(my_sleep2)   <cumtime>  test.py:20 called by test.py:25(my_sleep1)
test.py:43(my_sleep3)   <cumtime>  test.py:25 called by test.py:20(my_sleep1)->test.py:26(my_sleep2)
...

(<cumtime> is a numeric time.)

Are there ways in Python to achieve it? How?

Addition.

My code of Profiler() does not do it now:

class Profiler:
    def __init__( self, dir ):
        self._profiler = cProfile.Profile()
        self._profiler.enable()

        self._dir = dir # profiler output is "/tmp/profiler/{key}/<files_here>"


    def stop( self ):
        profilerDir = self._dir

        self._profiler.disable()

        with open( os.path.join( profilerDir, datetime.now().strftime( "%d-%m-%y %H.%M.%S" ) ), 'w' ) as f:
            stat = pstats.Stats( self._profiler, stream = f ).sort_stats( 'pcalls' )
            stat.print_stats()  
            stat.print_callers()
            stat.print_callees()


    def __del__( self ):
        self.stop()

Upvotes: 1

Views: 1332

Answers (1)

Steve Barnes
Steve Barnes

Reputation: 28370

Yes, but in many cases it is not a sensible thing to do as one (slow) part of the code may be called many times in the execution, what you could do is to run a trace and use the output of that to sort the profile entries.

I.e. trace tells you the order of execution and that can be used to sort the profile data.

I would seriously consider taking a look at profile viewer tools such as runsnakerun for this, e.g. the following lets me see how much time was taken and where it was called from: enter image description here

Upvotes: 2

Related Questions