o
    ei;                     @  sn   d Z ddlmZ ddlmZ ddlmZmZ erddlZeG dd dZ	eG dd	 d	Z
G d
d dZdS )a  
Dynamo Profiler - tracks where Dynamo spends time during compilation.

This module provides profiling functionality for Dynamo tracing, showing per-function
cumtime (inclusive) and tottime (exclusive) in a cProfile-compatible format.
The output can be visualized with tools like snakeviz.

Usage:
    # Enable via config (prints pstats output):
    torch._dynamo.config.dynamo_profiler = True

    # Or save to file for snakeviz:
    torch._dynamo.config.dynamo_profiler = "/tmp/dynamo.prof"
    # Then: snakeviz /tmp/dynamo.prof
    )annotations)	dataclass)AnyTYPE_CHECKINGNc                   @  s   e Zd ZU dZded< ded< ded< ded< ded< ded	< ded
< dZded< dZded< dZded< dZded< dZ	ded< e
d)ddZe
d*ddZe
d*ddZe
d*dd Ze
d+d"d#Ze
d,d%d&Zd-d'd(ZdS ).FunctionTraceTiminga+  
    Timing data for a single inlined function trace.

    Follows cProfile conventions:
    - cumtime: total time in function including all subcalls (inclusive)
    - tottime: time in function excluding subcalls (exclusive)
    - caller info: who called this function (for building call graph)
    str	func_namefilenameintfirstlineno
cumtime_ns
tottime_nsbytecode_countinline_depthN
str | Nonecaller_func_namecaller_filenamez
int | Nonecaller_firstlinenoTboolis_primitive_call  tuple[tuple[str, str, int], ...]
call_stackreturnc                 C     | j S Nr   selfr   r   g/var/www/addictedbytheproject.nl/epg/venv/lib/python3.10/site-packages/torch/_dynamo/dynamo_profiler.pytrace_time_ns=      z!FunctionTraceTiming.trace_time_nsfloatc                 C  
   | j d S Ng    .Ar   r   r   r   r   trace_time_msA      
z!FunctionTraceTiming.trace_time_msc                 C  r#   r$   r   r   r   r   r   
cumtime_msE   r&   zFunctionTraceTiming.cumtime_msc                 C  r#   r$   )r   r   r   r   r   
tottime_msI   r&   zFunctionTraceTiming.tottime_mstuple[str, int, str] | Nonec                 C  s&   | j dur| jp	d| jpd| j fS dS )z/Return caller as a pstats-compatible key tuple.N r   )r   r   r   r   r   r   r   
caller_keyM   s   
zFunctionTraceTiming.caller_keytuple[str, int, str]c                 C  s   | j | j| jfS )z6Return this function as a pstats-compatible key tuple.r	   r   r   r   r   r   r   func_keyX   s   zFunctionTraceTiming.func_keyc                 C  sB   d| j  d| j d| j d| jdd| jdd| j d| j d	S )
NzFunctionTraceTiming(z at :z
, cumtime=.2fzms, tottime=zms, bytecode=z, depth=))r   r	   r   r'   r(   r   r   r   r   r   r   __repr__]   s   zFunctionTraceTiming.__repr__)r   r
   )r   r"   )r   r)   )r   r,   )r   r   )__name__
__module____qualname____doc____annotations__r   r   r   r   r   propertyr    r%   r'   r(   r+   r.   r2   r   r   r   r   r      s6   
 

r   c                   @  sF   e Zd ZU dZded< ded< ded< ded< ded< d	Zd
ed< dS )ProfilerStackEntryz@Stack entry for tracking function timing in the Dynamo profiler.r   r   r	   r
   r   start_time_nschild_time_nsTr   r   N)r3   r4   r5   r6   r7   r   r   r   r   r   r9   e   s   
 r9   c                   @  s   e Zd ZdZd2ddZd3dd	Zd4ddZd5ddZd6ddZd7ddZ	d8ddZ
d9dd Z	"d:d;d(d)Z	!d<d=d,d-Z	.d>d?d0d1Zd!S )@DynamoProfilerStatez:State for Dynamo profiler tracking function trace timings.r   Nonec                 C  s   g | _ g | _d S r   )timingsstackr   r   r   r   __init__t   s   
zDynamoProfilerState.__init__timingr   c                 C  s   | j | dS )z)Record timing data for a traced function.N)r>   append)r   rA   r   r   r   record_timingx   s   z!DynamoProfilerState.record_timinglist[FunctionTraceTiming]c                 C  r   )zGet all recorded timings.)r>   r   r   r   r   get_timings|   r!   zDynamoProfilerState.get_timingsr   r   r	   r   r
   r:   c              
     s>   t  fdd| jD  }| jt |d|d dS )z'Push a new entry onto the timing stack.c                 3  s.    | ]}|j ko|j ko|jkV  qd S r   r   r	   r   .0entryr-   r   r   	<genexpr>   s    

z+DynamoProfilerState.push.<locals>.<genexpr>r   )r   r	   r   r:   r;   r   N)anyr?   rB   r9   )r   r   r	   r   r:   is_primitiver   r-   r   push   s   
zDynamoProfilerState.pushProfilerStackEntry | Nonec                 C  s   | j r| j  S dS )z(Pop the top entry from the timing stack.N)r?   popr   r   r   r   rO      s   
zDynamoProfilerState.popchild_cumtime_nsc                 C  s"   | j r| j d  j|7  _dS dS )zGAdd the child's cumulative time to the parent's child_time accumulator.N)r?   r;   )r   rP   r   r   r   add_child_time   s   z"DynamoProfilerState.add_child_timetuple[str, str, int] | Nonec                 C  s$   | j r| j d }|j|j|jfS dS )zLGet the current caller (top of stack) as (func_name, filename, firstlineno).rQ   N)r?   r   r	   r   )r   rI   r   r   r   get_current_caller   s   
z&DynamoProfilerState.get_current_callerr   c                 C  s   t dd | jD S )zOGet the full current call stack as tuple of (func_name, filename, firstlineno).c                 s  s     | ]}|j |j|jfV  qd S r   rF   rG   r   r   r   rJ      s    
z5DynamoProfilerState.get_call_stack.<locals>.<genexpr>)tupler?   r   r   r   r   get_call_stack   s   z"DynamoProfilerState.get_call_stackNFoutput_filer   	print_rawr   pstats.Statsc                 C  s  ddl }ddl}ddl}ddl}|t}i }i }	| jD ]}
|
j|
j|
j	f}||vr7ddddd||< i |	|< || }|d  d7  < |d  |
j
d 7  < |
jrd|d	  d7  < |d
  |
jd 7  < |
jdur|
j|
jpod|
jpsdf}||	| vrddddd|	| |< |	| | }|d  d7  < |d  |
j
d 7  < |d
  |
jd 7  < |
jr|d	  d7  < q|rUt| dd dd}td tdddd	dddddd
dd td d}d}|D ]N\\}}}}|d }|d	 }|d d }|d
 d }||7 }||7 }d|v r|dd n|}t|dd|dd|dd|dd| d| d| d qtd tdt| j d t|  td!|d"d#|d"d$ t|	 D ]}|	| D ]}||vruddddd||< i |	|< qaq[i }| D ]4\}}i }|	|  D ]\}}|d |d	 |d |d
 f||< q|d	 |d |d |d
 |f||< q| }|  |  |j|| d%}||_td&d' | D |_td(d' | D |_ td)d' | D |_!|r|"| |#d*|| |S )+zGenerate pstats.Stats object from recorded timings.

        Args:
            output_file: Optional file path to save the stats.
            print_raw: If True, print raw aggregate timings before returning.
        r   Ng        )ncallspcallstottimecumtimerZ      r\   g    eAr[   r]   r*   c                 S  s   | d d S )Nr^   r]   r   )xr   r   r   <lambda>   s    z5DynamoProfilerState.generate_pstats.<locals>.<lambda>T)keyreversez 
=== Aggregate Timings (raw) ===z>8 z>12z
  functionzP--------------------------------------------------------------------------------i  /rQ   z>10.2fzms zms  z (r/   r1   zTotal timings: z, unique functions: zSum tottime: r0   zms, Sum cumtime: ms)streamc                 s      | ]}|d  V  qdS )r^   Nr   rH   sr   r   r   rJ   ;      z6DynamoProfilerState.generate_pstats.<locals>.<genexpr>c                 s  rg   )r   Nr   rh   r   r   r   rJ   <  rj   c                 s  rg   )   Nr   rh   r   r   r   rJ   =  rj   z/Saved pstats to %s. Visualize with: snakeviz %s)$cProfileiologgingpstats	getLoggerr3   r>   r	   r   r   r   r   r   r   r   r   sorteditemsprintsplitlenlistkeysProfileenabledisableStatsStringIOstatssumvaluestotal_calls
prim_callstotal_tt
dump_statsinfo)r   rW   rX   rl   rm   rn   ro   log
aggregatedcaller_edgestra   aggr+   edgesorted_itemstotal_cumtimetotal_tottimer	   linenor   rZ   r[   r\   r]   
short_file
stats_dictcallersdummy_profiler}   r   r   r   generate_pstats   s   	



" 

	
z#DynamoProfilerState.generate_pstatsprofile_filesvg_filec              
   C  sr  ddl }ddl}ddl}|dstd dS |ds"td dS |du r0|ddd d	 }zn|jdd
dddd|g|j|jd}|jddd|g|j|j|jd}|j	  |
 \}}	|
 \}}
|jdkrttd|
   W dS |jdkrtd|	   W dS |j|std|  W dS td|  |W S  ty } ztd|  W Y d}~dS d}~ww )a{  Generate an SVG call graph from a profile file using gprof2dot and graphviz.

        Args:
            profile_file: Path to the pstats profile file.
            svg_file: Optional path for the output SVG. If not provided, uses
                profile_file with .svg extension.

        Returns:
            Path to the generated SVG file, or None if generation failed.
        r   N	gprof2dotz8gprof2dot not found. Install with: pip install gprof2dotdotz3graphviz 'dot' not found. Install graphviz package..r^   z.svgz-fro   z"--node-label=total-time-percentagez!--node-label=self-time-percentagez--node-label=total-time)stdoutstderrz-Tsvgz-o)stdinr   r   zgprof2dot failed: zgraphviz dot failed: zSVG file was not created: zSVG call graph saved to: zFailed to generate SVG: )osshutil
subprocesswhichrs   rsplitPopenPIPEr   closecommunicate
returncodedecodepathisfile	Exception)r   r   r   r   r   r   r   r   _dot_errgprof2dot_errer   r   r   generate_svgI  sf   

	



z DynamoProfilerState.generate_svgTr   c                 C  sx   ddl }| js	dS | j|dd}td |j|_|d  |r8td|  td|  |r:| | dS dS dS )	a#  Print profiler stats to stdout and optionally save to file.

        Args:
            output_file: Optional path to save the pstats profile.
            generate_svg: If True and output_file is provided, also generate an SVG
                call graph using gprof2dot and graphviz.
        r   NT)rX   z!
=== Dynamo Profiler (pstats) ===
cumulativez
Profile saved to: zVisualize with: snakeviz )	sysr>   r   rs   r   rf   
sort_statsprint_statsr   )r   rW   r   r   r}   r   r   r   r     s   
zDynamoProfilerState.dump_stats)r   r=   )rA   r   r   r=   )r   rD   )
r   r   r	   r   r   r
   r:   r
   r   r=   )r   rN   )rP   r
   r   r=   )r   rS   )r   r   )NF)rW   r   rX   r   r   rY   r   )r   r   r   r   r   r   )NT)rW   r   r   r   r   r=   )r3   r4   r5   r6   r@   rC   rE   rM   rO   rR   rT   rV   r   r   r   r   r   r   r   r<   q   s"    







 Kr<   )r6   
__future__r   dataclassesr   typingr   r   ro   r   r9   r<   r   r   r   r   <module>   s    I