U
    祡c                      @   s  d Z ddlmZmZmZ ddlZddlZddlmZ ddl	m
Z
 ddlmZmZ ddlmZ G dd	 d	eZeZed
ddZG dd deZG dd deZzRddlmZmZ G dd deZe  reZne  reZne  reZW nl ek
r\   z ddlmZ ddlm Z m!Z! W n  ek
rB   e"d Y nX G dd deZ#e#ZY nX G dd deZ$ee$ d
ddZ%e&d
ddZ'dS )a  
This module queries process memory allocation metrics from the operating
system. It provides a platform independent layer to get the amount of virtual
and physical memory allocated to the Python process.

Different mechanisms are implemented: Either the process stat file is read
(Linux), the `ps` command is executed (BSD/OSX/Solaris) or the resource module
is queried (Unix fallback). On Windows try to use the win32 module if
available. If all fails, return 0 for each attribute.

Windows without the win32 module is not supported.

    >>> from pympler.process import ProcessMemoryInfo
    >>> pmi = ProcessMemoryInfo()
    >>> print ("Virtual size [Byte]: " + str(pmi.vsz)) # doctest: +ELLIPSIS
    Virtual size [Byte]: ...
    )IterableListTupleN)PAGESIZE)getpid)PopenPIPE)ppc                   @   sZ   e Zd ZdZeZddddZedddZe	ddd	Z
d eeeef  d
ddZdS )_ProcessMemoryInfoa   Stores information about various process-level memory metrics. The
    virtual size is stored in attribute `vsz`, the physical memory allocated to
    the process in `rss`, and the number of (major) pagefaults in `pagefaults`.
    On Linux, `data_segment`, `code_segment`, `shared_segment` and
    `stack_segment` contain the number of Bytes allocated for the respective
    segments.  This is an abstract base class which needs to be overridden by
    operating system specific implementations. This is done when importing the
    module.
    Nreturnc                 C   sF   t  | _d| _d| _d| _g | _d| _d| _d| _d| _	| 
 | _d S )Nr   )r   pidrssvsz
pagefaultsos_specificdata_segmentcode_segmentshared_segmentstack_segmentupdate	availableself r   3/tmp/pip-unpacked-wheel-8ad_c8mj/pympler/process.py__init__,   s    z_ProcessMemoryInfo.__init__c                 C   s   d| j j| j| jf S )Nz<%s vsz=%d rss=%d>)	__class____name__r   r   r   r   r   r   __repr__:   s     z_ProcessMemoryInfo.__repr__c                 C   s   dS )z
        Refresh the information using platform instruments. Returns true if
        this operation yields useful values on the current platform.
        Fr   r   r   r   r   r   >   s    z_ProcessMemoryInfo.update)otherr   c                 C   s$   d| j |j  fd| j|j fg}|S )NzResident set size (delta)zVirtual size (delta))r   r   )r   r    Zdiffr   r   r   __sub__E   s    z_ProcessMemoryInfo.__sub__)r   
__module____qualname____doc__r   pagesizer   strr   boolr   r   r   intr!   r   r   r   r   r
      s   
r
   r   c                   C   s
   t   S )z`
    Convenience function to check if the current platform is supported by this
    module.
    )ProcessMemoryInfor   r   r   r   r   is_availableO   s    r*   c                   @   s   e Zd ZedddZdS )_ProcessMemoryInfoPSr   c                 C   s   z t dd| j ddgttd}W n tk
r4   Y nPX | d  }|jdkrt|dkrt|d d	 | _	t|d
 d	 | _
dS dS )z
        Get virtual and resident size of current process via 'ps'.
        This should work for MacOS X, Solaris, Linux. Returns true if it was
        successful.
        z/bin/psz-p%sz-ozrss,vsz)stdoutstderrr         TF)r   r   r   OSErrorcommunicatesplit
returncodelenr(   r   r   )r   psr   r   r   r   Y   s     
z_ProcessMemoryInfoPS.updateNr   r"   r#   r'   r   r   r   r   r   r+   W   s   r+   c                   @   s4   e Zd Zddddddddd	d
d
ZedddZdS )_ProcessMemoryInfoProczPeak virtual memory sizezVirtual memory sizezLocked memory sizezPeak resident set sizezResident set sizezSize of stack segmentzSize of data segmentzSize of code segmentzShared library code sizezPage table entries size)
ZVmPeakZVmSizeZVmLckZVmHWMZVmRSSVmStkVmDataVmExeVmLibZVmPTEr   c              	   C   sN  zt d}t d}W n tk
r*   Y dS X |  }t|d | _t|d | j | _t|d | _|	 D ]}z|dd\}}W n t
k
r   Y qpY nX | }ttd	d
d}|dkr||| _n<|dkr||| _n(|dkr||| _n|dkr
||| _| j|d}|rp| j|t||f qp|  |  dS dS )z|
        Get virtual size of current process by reading the process' stat file.
        This should work for Linux.
        z/proc/self/statz/proc/self/statusF         :   )xr   c                 S   s   t |  d d S )Nr   r0   )r(   r4   )rD   r   r   r   size_in_bytes   s    z4_ProcessMemoryInfoProc.update.<locals>.size_in_bytesr<   r=   r>   r;    TN)openIOErrorreadr4   r(   r   r%   r   r   	readlines
ValueErrorstripr&   r   r   r   r   key_mapgetr   appendr	   close)r   statstatusstatsentrykeyvaluerE   r   r   r   r   |   s<    


z_ProcessMemoryInfoProc.updateN)r   r"   r#   rM   r'   r   r   r   r   r   r:   m   s   r:   )	getrusageRUSAGE_SELFc                   @   s   e Zd ZedddZdS )_ProcessMemoryInfoResourcer   c                 C   s^   t t}|jd | _|jd | _|jd | _|jd | _	| j| j | j	 | _
|j| _| jdkS )a  
            Get memory metrics of current process through `getrusage`.  Only
            available on Unix, on Linux most of the fields are not set,
            and on BSD units are used that are not very helpful, see:

            http://www.perlmonks.org/?node_id=626693

            Furthermore, getrusage only provides accumulated statistics (e.g.
            max rss vs current rss).
            r0   r   )rW   rX   Z	ru_maxrssr   Zru_idrssr   Zru_ixrssr   Zru_isrssr   r   Z	ru_majfltr   )r   usager   r   r   r      s    
z!_ProcessMemoryInfoResource.updateNr9   r   r   r   r   rY      s   rY   )GetProcessMemoryInfo)GetCurrentProcessGlobalMemoryStatusExz5Please install pywin32 when using pympler on Windows.c                   @   s   e Zd ZedddZdS )_ProcessMemoryInfoWin32r   c                 C   s>   t  }t|}t }|d |d  | _|d | _|d | _dS )NZTotalVirtualZAvailVirtualZWorkingSetSizeZPageFaultCountT)r\   r[   r]   r   r   r   )r   Zprocess_handleZmeminfoZ	memstatusr   r   r   r      s    

z_ProcessMemoryInfoWin32.updateNr9   r   r   r   r   r^      s   r^   c                   @   s    e Zd ZdZejdddZdS )
ThreadInfoz+Collect information about an active thread.)threadc                 C   s   |j | _ |j| _|j| _d S )N)identnamedaemon)r   r`   r   r   r   r      s    zThreadInfo.__init__N)r   r"   r#   r$   	threadingThreadr   r   r   r   r   r_      s   r_   c                   C   s   dd t  D S )z#Get a list of `ThreadInfo` objects.c                 S   s   g | ]}t |qS r   )r_   ).0r`   r   r   r   
<listcomp>   s     z'get_current_threads.<locals>.<listcomp>)rd   	enumerater   r   r   r   get_current_threads   s    ri   c                   C   s   t  S )z!Get the ID of the current thread.)rd   	get_identr   r   r   r   get_current_thread_id   s    rk   )(r$   typingr   r   r   loggingrd   Zmmapr   osr   
subprocessr   r   Zpympler.util.stringutilsr	   objectr
   r)   r'   r*   r+   r:   resourcerW   rX   rY   r   ImportErrorZwin32processr[   win32apir\   r]   warnr^   r_   ri   r(   rk   r   r   r   r   <module>   s@   -:



	