o
    j9:j"                     @  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 ddlm	Z	m
Z
mZ ddlmZ e
r3d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 dB edB 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)Callable)AnyTYPE_CHECKING	TypeAlias)Self)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intreturnNonec                 C  s   || _ g | _d S N)r   heap)selfr    r   d/home/nk/hobo-godmode/plappi-mvp/.venv/lib/python3.10/site-packages/torch/_dynamo/metrics_context.py__init__(   s   
zTopN.__init__keyr   valc                 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__1   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>5   s    z TopN.__iter__.<locals>.<genexpr>T)reverse)sortedr   r   r   r   r   __iter__4   s   zTopN.__iter__N)r   )r   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*   r   r   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   c                 C  s,   | j dkri | _t | _|  j d7  _ | S )z/
        Initialize metrics recording.
        r      )r0   r.   timetime_nsr/   r   r   r   r   	__enter__L   s
   

zMetricsContext.__enter__exc_typetype[BaseException] | None	exc_valueBaseException | None
_tracebackr   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.
        r3   r   z0Unexpected exception logging compilation metricsN)	r0   r4   r5   r-   r/   r.   	Exceptionlog	exception)r   r7   r9   r;   end_time_nsr   r   r   __exit__X   s   	

zMetricsContext.__exit__boolc                 C  s
   | j dkS )z4
        True if we've entered the context.
        r   )r0   r   r   r   r   in_progressl   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r0   RuntimeErrorr.   r   rC   rE   r   r   r   	incrementr   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rL   r   r   r"   }   s    
z/MetricsContext._render_edits.<locals>.<genexpr>)rO   r1   )r   rL   r   rS   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 rG   z

RuntimeError: Metric 'z]' has already been set in the current context (see above for current and previous traceback).r3   skipN)r0   rI   r.   rT   r1   appendr	   extract)r   rC   rE   rU   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   rV   rG   NrH   )r   rC   r   rE   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).r3   rW   N)r0   rI   r.   keysrT   r[   r1   rY   r	   rZ   update)r   r]   rU   existingr   r   r   ra      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_   r3   N)r0   rI   ra   )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 rG   N)r0   rI   r.   r[   r   rJ   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)r0   r.   r
   r   )r   rC   r   r   r   r   r   	add_top_n   s
   

zMetricsContext.add_top_nNr,   r*   r   r   )r   r   )r7   r8   r9   r:   r;   r   r   r   )r   rA   )rC   rD   rE   r   r   r   )rL   rM   r   rD   )F)rC   rD   rE   r   rU   rA   r   r   )rC   rD   r   rD   rE   r   r   r   )r]   r^   rU   rA   r   r   )r]   r^   r   r   )rC   rD   rE   r   r   r   )rC   rD   r   r   r   r   r   r   )r&   r'   r(   r   r6   r@   rB   rK   rT   r[   r\   ra   rc   rd   re   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*   r   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.   r/   r2   r   r   r   r      s   
zRuntimeMetricsContext.__init__NrC   rD   rE   r   extradict[str, Any] | Nonec                 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 )rF   r   N)r.   r4   r5   r/   items)r   rC   rE   rh   rR   vr   r   r   rK      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.   r4   r5   r-   r/   r<   r=   r>   )r   r?   r   r   r   finish   s   
zRuntimeMetricsContext.finishrf   r   )rC   rD   rE   r   rh   ri   r   r   )r   r   )r&   r'   r(   r   rK   rl   r   r   r   r   rg      s
    
rg   )r)   
__future__r   r   loggingr4   collections.abcr   typingr   r   r   typing_extensionsr   r   torch.utils._tracebackr	   	getLoggerr&   r=   r
   r   dictrD   typeBaseExceptionr*   __annotations__r+   rg   r   r   r   r   <module>   s*    
  