B
    ^\)                 @   s  d Z ddlmZmZmZ ddlZddlmZmZ ddl	Z	ddl
Z
ddlZddlmZ ddlZddlmZ ddlmZmZmZ dd	lmZ d
d Zdd Zdd Zd)ddZdd Zdd Zdd Zd*ddZddddd fdd Zdddd!dd"d fd#d$Zd+d%d&Z d'd( Z!dS ),a,   This module contains utility functions to construct and manipulate counting
data structures for frames.

When performing statistical profiling we obtain many call stacks.  We aggregate
these call stacks into data structures that maintain counts of how many times
each function in that call stack has been called.  Because these stacks will
overlap this aggregation counting structure forms a tree, such as is commonly
visualized by profiling tools.

We represent this tree as a nested dictionary with the following form:

    {
     'identifier': 'root',
     'description': 'A long description of the line of code being run.',
     'count': 10  # the number of times we have seen this line
     'children': {  # callers of this line. Recursive dicts
         'ident-b': {'description': ...
                   'identifier': 'ident-a',
                   'count': ...
                   'children': {...}},
         'ident-b': {'description': ...
                   'identifier': 'ident-b',
                   'count': ...
                   'children': {...}}}
    }
    )print_functiondivisionabsolute_importN)defaultdictdeque)sleep   )time)format_timecolor_ofparse_timedelta)get_thread_identityc             C   s0   | dkrdS d | jj| jjt| jjfS dS )zq A string identifier from a frame

    Strings are cheaper to use as indexes into dicts than tuples or dicts
    NNone;)joinf_codeco_nameco_filenamestrco_firstlineno)frame r   2lib/python3.7/site-packages/distributed/profile.py
identifier+   s
    
r   c             C   s>   | j }d|j| j|jf }t|j| j| j }|d | S )z> Render a frame as a line for inclusion into a text traceback z  File "%s", line %s, in %sz
	)r   r   f_linenor   	linecachegetline	f_globalslstrip)r   cotextliner   r   r   
repr_frame8   s    
r"   c             C   s2   | j }t|j| j| j }|j|j| j|dS )N)filenamenameline_numberr!   )r   r   r   r   r   r   r   r   )r   r   r!   r   r   r   
info_frameB   s    r&   c                s   |dk	r"t  fdd|D r"dS  j}|dk	rb|dksF|jj|sbt| ||d}|dkrbdS t }y|d | }W n2 tk
r   dt i |d}||d |< Y nX |d	  d
7  < |dk	r|S |d	  d
7  < dS )aZ   Add counts from a frame stack onto existing state

    This recursively adds counts to the existing state dictionary and creates
    new entries for new functions.

    Example
    -------
    >>> import sys, threading
    >>> ident = threading.get_ident()  # replace with your thread of interest
    >>> frame = sys._current_frames()[ident]
    >>> state = {'children': {}, 'count': 0, 'description': 'root',
    ...          'identifier': 'root'}
    >>> process(frame, None, state)
    >>> state
    {'count': 1,
     'identifier': 'root',
     'description': 'root',
     'children': {'...'}}
    Nc             3   s   | ]} j j|V  qd S )N)r   r   endswith).0o)r   r   r   	<genexpr>_   s    zprocess.<locals>.<genexpr>F)stopchildrenr   )countdescriptionr,   r   r-   r   )	anyf_backr   r   r'   processr   KeyErrorr&   )r   childstater+   omitprevidentdr   )r   r   r1   K   s(    r1   c              G   s   | s
t  S dd | D }t|dkr4tdt| tt}x4| D ],}x&|d D ]}|| |d |  qPW qBW dd | D }tdd	 | D }| d
 d t	||| d
 d dS )z& Merge multiple frame states together c             S   s   h | ]}|d  qS )r   r   )r(   argr   r   r   	<setcomp>   s    zmerge.<locals>.<setcomp>r   zExpected identifiers, got %sr,   c             S   s   i | ]\}}t | |qS r   )merge)r(   kvr   r   r   
<dictcomp>   s    zmerge.<locals>.<dictcomp>c             s   s   | ]}|d  V  qdS )r-   Nr   )r(   r9   r   r   r   r*      s    zmerge.<locals>.<genexpr>r   r.   r   )r.   r,   r-   r   )
createlen
ValueErrorr   r   listappenditemssumdict)argssr,   r9   r3   r-   r   r   r   r;   {   s    

r;   c               C   s   di dddddddS )Nr   root )r#   r$   r%   r!   )r-   r,   r   r.   r   r   r   r   r   r?      s    r?   c             C   s0   g }x| r | t|  | j} qW |ddd S )zX Create a call text stack from a frame

    Returns
    -------
    list of strings
    N)rC   r"   r0   )r   Lr   r   r   
call_stack   s
    
rM   {Gz?c                s   g g 	g g g  g g 
g g g g  	
fdd| ddd dd D }	dd D  
|dS )	z Convert a profile state into data useful by Bokeh

    See Also
    --------
    distributed.bokeh.components.ProfilePlot
    c                s6  | d sd S  | 	 |  | || } |  |  
 t| d   | d } |d   |d   |d   |d  | d }y  t|d  W n tk
r     d Y nX || | d  }|}xB| d	  D ]2\}	}
|
d | }|
||| |d
  ||7 }qW d S )Nr-   r.   r#   r!   r%   r$   r   Zgrayr,   r   )rC   r
   r   
IndexErrorrD   )r4   startr+   ZheightwidthZdescr7   Zdeltaxr$   r3   )colors	filenamesheightsline_numberslinesnamesprofile_intervalstartsstatesstopstimestraversewidthsr   r   r^      s2    




zplot_data.<locals>.traverser   r   c             S   s   g | ]}d  d| qS )z{:.2f}%d   )format)r(   wr   r   r   
<listcomp>   s    zplot_data.<locals>.<listcomp>c             S   s   g | ]}|d  qS )r   r   )r(   rR   r   r   r   rc      s    )leftrightbottomrQ   topcolorr[   r#   r!   r%   r$   r	   Z
percentager   )r4   rY   Zpercentagesr   )rS   rT   rU   rV   rW   rX   rY   rZ   r[   r\   r]   r^   r_   r   	plot_data   s6    $!ri   Z20msZ2sc               C   s   dS )NFr   r   r   r   r   <lambda>   s    rj   c       	      C   s   t |}t |}t }t }xr| st || krN|t |f t }t }yt |  }W n tk
rr   d S X t|d ||d t| qW d S )N)r5   )	r   r?   r	   rC   sys_current_framesr2   r1   r   )		thread_idlogintervalcycler5   r+   recentZlastr   r   r   r   _watch   s    rr   i  c               C   s   dS )NFr   r   r   r   r   rj      s    c          
   C   sH   | d krt  } t|d}tjtd| |||||dd}d|_|  |S )N)maxlenZProfile)rm   ro   rp   rn   r5   r+   )targetr$   kwargsT)r   r   	threadingZThreadrr   ZdaemonrP   )rm   ro   rp   rs   r5   r+   rn   Zthreadr   r   r   watch   s    
rw   c       
         s   t  }|d krd}nt |f}|d kr0d }n"t |fd }|t krRd }|dkrl|d krlt  n,|d kr|t n|} fddt||D  tt	d  }	 st
 S |rt|	|}	|	S )Nr   r   c                s   g | ]} | qS r   r   )r(   i)historyr   r   rc   %  s    zget_profile.<locals>.<listcomp>)r	   bisectZbisect_leftZbisect_rightr@   rB   ranger;   toolzZpluckr?   )
ry   rq   rP   r+   keyZnowZistartZistopZiistopZprofr   )ry   r   get_profile  s&    

r~   c       	   
   K   s   ddl m}m} ddlm} d| kr0t| d} || d}|f ddi|}|jdd	d
dddd|d}d |_d |_	|ddd}|
| d|j_d|j_d|j_||fS )Nr   )ColumnDataSourcefigure)	HoverToolr[   )dataZtoolsZtaprd   re   rg   rf   rh   Zblack   )rh   Z
line_colorZ
line_widthsourceZfollow_mousea.  
            <div>
                <span style="font-size: 14px; font-weight: bold;">Name:</span>&nbsp;
                <span style="font-size: 10px; font-family: Monaco, monospace;">@name</span>
            </div>
            <div>
                <span style="font-size: 14px; font-weight: bold;">Filename:</span>&nbsp;
                <span style="font-size: 10px; font-family: Monaco, monospace;">@filename</span>
            </div>
            <div>
                <span style="font-size: 14px; font-weight: bold;">Line number:</span>&nbsp;
                <span style="font-size: 10px; font-family: Monaco, monospace;">@line_number</span>
            </div>
            <div>
                <span style="font-size: 14px; font-weight: bold;">Line:</span>&nbsp;
                <span style="font-size: 10px; font-family: Monaco, monospace;">@line</span>
            </div>
            <div>
                <span style="font-size: 14px; font-weight: bold;">Time:</span>&nbsp;
                <span style="font-size: 10px; font-family: Monaco, monospace;">@time</span>
            </div>
            <div>
                <span style="font-size: 14px; font-weight: bold;">Percentage:</span>&nbsp;
                <span style="font-size: 10px; font-family: Monaco, monospace;">@width</span>
            </div>
            )Zpoint_policyZtooltipsF)Zbokeh.plottingr   r   Zbokeh.modelsr   r|   ZdissocZquadZselection_glyphZnonselection_glyphZ	add_toolsZxaxisZvisibleZyaxisZgrid)	r   ru   r   r   r   r   ZfigrZhoverr   r   r   plot_figure2  s$    

r   )NN)rN   )NNNN)"__doc__Z
__future__r   r   r   rz   collectionsr   r   r   rk   rv   r	   r   r|   ZmetricsZutilsr
   r   r   Zcompatibilityr   r   r"   r&   r1   r;   r?   rM   ri   rr   rw   r~   r   r   r   r   r   <module>   s2   
	
0
F

