o
     Ǝi"                     @  s   U d Z ddlmZ ddlZddlZddlZddlmZmZm	Z	m
Z
 ddlmZmZ e
r1ddlmZ ddlmZ eeZG dd	 d	Zeeeeeef e	ee  e	e gdf Zd
ed< G dd dZG dd dZdS )a[  Metrics collection and management system for Dynamo.

This module provides context managers for gathering and reporting metrics during
compilation and runtime.

It includes two main components:
- MetricsContext: A context manager for collecting metrics during compilation, supporting
  nested contexts and various metric types (counters, sets, key-value pairs)
- RuntimeMetricsContext: A specialized context for runtime metrics collection that doesn't
  require explicit context management

The metrics system enables comprehensive monitoring and analysis of both compilation and
execution performance.
    )annotationsN)AnyCallableOptionalTYPE_CHECKING)Self	TypeAlias)Iterator)CapturedTracebackc                   @  s:   e Zd ZdZddddZdddZdddZdddZdS )TopNz_
    Helper to record a list of metrics, keeping only the top N "most expensive" elements.
       at_mostintc                 C  s   || _ g | _d S N)r   heap)selfr    r   Y/home/jeff/fluffinator/venv/lib/python3.10/site-packages/torch/_dynamo/metrics_context.py__init__'   s   
zTopN.__init__keyr   valreturnNonec                 C  s0   t | j| jk rtjntj}|| j||f d S r   )lenr   r   heapqheappushheappushpop)r   r   r   fnr   r   r   add+   s   zTopN.addc                 C  s
   t | jS r   )r   r   r   r   r   r   __len__0   s   
zTopN.__len__Iterator[tuple[Any, int]]c                 C  s   dd t | jddD S )Nc                 s  s    | ]	\}}||fV  qd S r   r   ).0r   r   r   r   r   	<genexpr>4   s    z TopN.__iter__.<locals>.<genexpr>T)reverse)sortedr   r   r   r   r   __iter__3   s   zTopN.__iter__N)r   )r   r   )r   r   r   r   r   r   )r   r   )r   r!   )__name__
__module____qualname____doc__r   r   r    r&   r   r   r   r   r   "   s    

r   r   
OnExitTypec                   @  s   e Zd Zd2ddZd3ddZd4ddZd5ddZd6ddZd7ddZd8d9d!d"Z	d:d$d%Z
d8d;d(d)Zd<d*d+Zd=d,d-Zd>d/d0Zd1S )?MetricsContexton_exitr+   c                 C  s"   || _ i | _d| _d| _g | _dS )aQ  
        Use this class as a contextmanager to create a context under which to accumulate
        a set of metrics, e.g., metrics gathered during a compilation. On exit of the
        contextmanager, call the provided 'on_exit' function and pass a dictionary of
        all metrics set during the lifetime of the contextmanager.
        r   N)_on_exit_metrics_start_time_ns_level_editsr   r-   r   r   r   r   >   s
   
zMetricsContext.__init__r   r   c                 C  s,   | j dkri | _t | _|  j d7  _ | S )z/
        Initialize metrics recording.
        r      )r1   r/   timetime_nsr0   r   r   r   r   	__enter__K   s
   

zMetricsContext.__enter__exc_typeOptional[type[BaseException]]	exc_valueOptional[BaseException]
_tracebackr   r   c                 C  sn   |  j d8  _ | j dksJ | j dkr5zt }| | j|| j|| W dS  ty4   td Y dS w dS )z>
        At exit, call the provided on_exit function.
        r4   r   z0Unexpected exception logging compilation metricsN)	r1   r5   r6   r.   r0   r/   	Exceptionlog	exception)r   r8   r:   r<   end_time_nsr   r   r   __exit__W   s   	

zMetricsContext.__exit__boolc                 C  s
   | j dkS )z4
        True if we've entered the context.
        r   )r1   r   r   r   r   in_progressk   s   
zMetricsContext.in_progressmetricstrvaluer   c                 C  sD   | j dkrtd| d|| jvrd| j|< | j|  |7  < dS )7
        Increment a metric by a given amount.
        r   zCannot increment  outside of a MetricsContextNr1   RuntimeErrorr/   r   rD   rF   r   r   r   	incrementq   s
   


zMetricsContext.incrementpredset[str]c                   s   dd  fdd| jD  S )Nz

c                 3  s.    | ]\}}| @ rd d |  V  qdS )zPrevious Traceback:
 N)joinformat)r"   ekrM   r   r   r#   |   s    
z/MetricsContext._render_edits.<locals>.<genexpr>)rP   r2   )r   rM   r   rT   r   _render_edits{   s   
zMetricsContext._render_editsF	overwritec                 C  sl   | j dkrtd| d|| jv r"|s"t| |hd| d | jtjdd|hf || j|< dS )	z
        Set a metric to a given value. Raises if the metric has been assigned previously
        in the current context.
        r   Cannot set rH   z

RuntimeError: Metric 'z]' has already been set in the current context (see above for current and previous traceback).r4   skipN)r1   rJ   r/   rU   r2   appendr
   extract)r   rD   rF   rV   r   r   r   set   s   


zMetricsContext.setr   c                 C  s@   | j dkrtd| d|| jvri | j|< || j| |< dS )a=  
        Treats a give metric as a dictionary and set the k and value within it.
        Note that the metric must be a dictionary or not present.

        We allow this to be called multiple times (i.e. for features, it's not uncommon
        for them to be used multiple times within a single compilation).
        r   rW   rH   NrI   )r   rD   r   rF   r   r   r   set_key_value   s
   


zMetricsContext.set_key_valuevaluesdict[str, Any]c                 C  s~   | j dkr	td| j | @ }|r'|s't| t| d| d | jtj	ddt| f | j
| dS )z
        Set multiple metrics directly. This method does NOT increment. Raises if any
        metric has been assigned previously in the current context and overwrite is
        not set to True.
        r   1Cannot update metrics outside of a MetricsContextz

RuntimeError: Metric(s) z_ have already been set in the current context.  (see above for current and previous traceback).r4   rX   N)r1   rJ   r/   keysrU   r\   r2   rZ   r
   r[   update)r   r^   rV   existingr   r   r   rb      s   

 zMetricsContext.updatec                 C  s.   | j dkr	td| j dkr| | dS dS )zA
        Update, but only when at the outermost context.
        r   r`   r4   N)r1   rJ   rb   )r   r^   r   r   r   update_outer   s
   

zMetricsContext.update_outerc                 C  sD   | j dkrtd| d|| jvrt | j|< | j| | dS )z8
        Records a metric as a set() of values.
        r   zCannot add rH   N)r1   rJ   r/   r\   r   rK   r   r   r   
add_to_set   s
   

zMetricsContext.add_to_setr   c                 C  s:   | j dkrdS || jvrt | j|< | j| || dS )z;
        Records a metric as a TopN set of values.
        r   N)r1   r/   r   r   )r   rD   r   r   r   r   r   	add_top_n   s
   

zMetricsContext.add_top_nNr-   r+   )r   r   )r8   r9   r:   r;   r<   r   r   r   )r   rB   )rD   rE   rF   r   r   r   )rM   rN   r   rE   )F)rD   rE   rF   r   rV   rB   r   r   )rD   rE   r   rE   rF   r   r   r   )r^   r_   rV   rB   r   r   )r^   r_   r   r   )rD   rE   rF   r   r   r   )rD   rE   r   r   r   r   r   r   )r'   r(   r)   r   r7   rA   rC   rL   rU   r\   r]   rb   rd   re   rf   r   r   r   r   r,   =   s    









	
r,   c                   @  s.   e Zd ZdddZ	ddddZdddZdS )RuntimeMetricsContextr-   r+   c                 C  s   || _ i | _d| _dS )z
        Similar to MetricsContext, but used to gather the runtime metrics that are
        decoupled from compilation, where there's not a natural place to insert a
        context manager.
        r   N)r.   r/   r0   r3   r   r   r   r      s   
zRuntimeMetricsContext.__init__NrD   rE   rF   r   extraOptional[dict[str, Any]]r   r   c                 C  sp   | j st | _|| j vrd| j |< | j |  |7  < |r4| D ]\}}|| j vr3|dur3|| j |< q!dS dS )rG   r   N)r/   r5   r6   r0   items)r   rD   rF   ri   rS   vr   r   r   rL      s   



zRuntimeMetricsContext.incrementc                 C  sl   | j r4z,zt }| | j|| j dd W n ty#   td Y nw W i | _ dS W i | _ dS i | _ w dS )zW
        Call the on_exit function with the metrics gathered so far and reset.
        Nz,Unexpected exception logging runtime metrics)r/   r5   r6   r.   r0   r=   r>   r?   )r   r@   r   r   r   finish   s   
zRuntimeMetricsContext.finishrg   r   )rD   rE   rF   r   ri   rj   r   r   )r   r   )r'   r(   r)   r   rL   rm   r   r   r   r   rh      s
    
rh   )r*   
__future__r   r   loggingr5   typingr   r   r   r   typing_extensionsr   r   collections.abcr	   torch.utils._tracebackr
   	getLoggerr'   r>   r   r   dictrE   typeBaseExceptionr+   __annotations__r,   rh   r   r   r   r   <module>   s(    
  