profiling#

ProfileNode#

class onnx_array_api.profiling.ProfileNode(filename: str, line: int, func_name: str, nc1: int, nc2: int, tin: float, tall: float)[source]#

Graph structure to represent a profiling.

Parameters:
  • filename – filename

  • line – line number

  • func_name – function name

  • nc1 – number of calls 1

  • nc2 – number of calls 2

  • tin – time spent in the function

  • tout – time spent in the function and in the sub functions

profile#

onnx_array_api.profiling.profile(fct: Callable, sort: str = 'cumulative', rootrem: str | None = None, as_df: bool = False, return_results: bool = False, **kwargs) str[source]#

Profiles the execution of a function.

Parameters:
  • fct – function to profile

  • sort – see sort_stats

  • rootrem – root to remove in filenames

  • as_df – return the results as a dataframe and not text

  • return_results – if True, return results as well (in the first position)

  • kwargs – additional parameters used to create the profiler, see cProfile.Profile

Returns:

raw results, statistics text dump (or dataframe is as_df is True)

(Source code, png, hires.png, pdf)

../_images/profiling-1.png

profile2graph#

onnx_array_api.profiling.profile2graph(ps: Stats, clean_text: Callable | None = None, verbose: bool = False, fLOG: Callable | None = None) ProfileNode[source]#

Converts profiling statistics into a graphs.

Parameters:
  • ps – an instance of pstats

  • clean_text – function to clean function names

  • verbose – verbosity

  • fLOG – logging function

Returns:

an instance of class @see cl ProfileNode

pyinstrument has a nice display to show time spent and call stack at the same time. This function tries to replicate that display based on the results produced by module cProfile. Here is an example.

<<<

import time
from onnx_array_api.profiling import profile, profile2graph


def fct0(t):
    time.sleep(t)


def fct1(t):
    time.sleep(t)


def fct2():
    fct1(0.1)
    fct1(0.01)


def fct3():
    fct0(0.2)
    fct1(0.5)


def fct4():
    fct2()
    fct3()


ps = profile(fct4)[0]
root, nodes = profile2graph(ps, clean_text=lambda x: x.split("/")[-1])
text = root.to_text()
print(text)

>>>

    fct1                                                         --  3  3 -- 0.00003 0.61117 -- :11:fct1 (fct1)
        <built-in method time.sleep>                             --  3  3 -- 0.61114 0.61114 -- ~:0:<built-in method time.sleep> (<built-in method time.sleep>) +++
    fct4                                                         --  1  1 -- 0.00001 0.81212 -- :25:fct4 (fct4)
        fct2                                                     --  1  1 -- 0.00001 0.11055 -- :15:fct2 (fct2)
            fct1                                                 --  2  2 -- 0.00002 0.11054 -- :11:fct1 (fct1) +++
        fct3                                                     --  1  1 -- 0.00002 0.70156 -- :20:fct3 (fct3)
            fct0                                                 --  1  1 -- 0.00001 0.20091 -- :7:fct0 (fct0)
                <built-in method time.sleep>                     --  1  1 -- 0.20089 0.20089 -- ~:0:<built-in method time.sleep> (<built-in method time.sleep>) +++
            fct1                                                 --  1  1 -- 0.00001 0.50063 -- :11:fct1 (fct1) +++
    <built-in method time.sleep>                                 --  4  4 -- 0.81203 0.81203 -- ~:0:<built-in method time.sleep> (<built-in method time.sleep>)