ó
ÔŒ\c           @  sø   d  d l  m Z d  d l Z d  d l Z d  d l Z d  d l Z d  d l Z d  d l Z d  d l Z d  d l	 Z	 e	 j
 j d ƒ Z d „  Z d „  Z d „  Z d d „ Z d d	 g d
 „ Z d d d „ Z i  a d a e d „ Z d „  Z d „  Z d S(   iÿÿÿÿ(   t   print_functionNt   memoryc         C  s£   t  ƒ  t  d j |  ƒ ƒ x‚ t j D]w } d } d } t | d ƒ rW | j } d } n  y d t j | ƒ d } Wn n Xt  d | t | ƒ d  | ƒ q$ Wd	 S(
   sI   
    Prints out the garbage after collecting a generation of memory.
    s'   Garbage after collecting generation {}:t    t   cell_contentss   cell: s    (t   )s    -i    N(	   t   printt   formatt   gct   garbaget   hasattrR   t   inspectt   getfilet   repr(   t   gent   it   prefixt   suffix(    (    s   renpy/memory.pyt   print_garbage'   s    		c         C  s(   t  j j |  d ƒ t j d |  ƒ d  S(   Ns   
s   %s(   t   syst   stdoutt   writet
   memory_log(   t   s(    (    s   renpy/memory.pyR   ?   s    c           sz  i  ‰ i  ‰ t  ƒ  ‰  ‡  ‡ ‡ ‡ f d †  ‰ ˆ d  |  | ƒ x{ t rº t  d „  ˆ  Dƒ ƒ } t  d „  ˆ  Dƒ ƒ } | | ‰ | | ‰ ˆ r˜ ˆ r˜ Pn  t  ‡ ‡ f d †  ˆ  Dƒ ƒ ‰  q@ Wx¸ ˆ  rut ƒ  t d ƒ t ˆ  ƒ d } xŠ | ˆ  k rqˆ  j | ƒ t d | ƒ t d | d	 d
 ˆ | d ƒ g  ˆ  D]  } | d | d k r4| ^ q4} | sdPn  | d } qè Wq¾ Wd  S(   Nc           sµ  t  | ƒ } |  d  k	 r1 ˆ j |  | | f ƒ n  | ˆ k rA d  S| ˆ | <t | t t t j t j t j	 f ƒ r t
 | ƒ } n&t | t t f ƒ rà t | ƒ d k rÀ t
 | ƒ j d ƒ } q§t
 | d  d ƒ j d ƒ } nÇ t | t t f ƒ rd | j j d } n› t | t ƒ r2d | j j d } nu t | t j ƒ red j | j j | j j ƒ } nB t | t ƒ rd j t | ƒ j ƒ } n d j t | ƒ j ƒ } | ˆ | <t | t t f ƒ rx9 t | ƒ D]( \ } } ˆ | | d	 j | | ƒ ƒ qÓWn  t | t ƒ rMx| j ƒ  D]( \ } } ˆ | | d	 j | | ƒ ƒ qWndt | t j ƒ ryˆ | | j | d
 ƒ n8y | j d ƒ ‰  Wn g  ‰  n X‡  f d †  }	 |	 d i  ƒ }
 t |
 t ƒ rxI |
 j ƒ  D]$ \ } } ˆ | | | d | ƒ qÖWn ˆ | |
 | d ƒ x? t |	 d g  ƒ ƒ D]( \ } } ˆ | | d j | | ƒ ƒ q+WxW |	 d g  ƒ D]F } t | ƒ d k r…qgn  | \ } } ˆ | | d	 j | | ƒ ƒ qgWd  S(   NiP   s   utf-8s   ...t   <t   >s   <method {0}.{1}>s   <{0}>s   BAD TYPE <{0}>s
   {0}[{1!r}]s   .im_selfi   c           s2   |  t  ˆ  ƒ k  r* ˆ  |  d  k	 r* ˆ  |  S| Sd  S(   N(   t   lent   None(   t   idxt   default(   t	   reduction(    s   renpy/memory.pyt   getƒ   s    "t   .s   .__getstate__()i   s   {0}[{1}]i   (   t   idR   t   addt
   isinstancet   intt   floatt   typest   NoneTypet
   ModuleTypet	   ClassTypeR   t   strt   unicodeR   t   encodet   tuplet   listt	   __class__t   __name__t   dictt
   MethodTypeR   t   im_classt   im_funct   objectt   typet	   enumeratet	   iteritemst   im_selft   __reduce_ex__(   t   old_idot   ot   patht   idot   o_reprR   t   oot   kt   vR   t   state(   t   edgest   o_repr_cachet   pathst   visit(   R   s   renpy/memory.pyRF   J   s^    
' !
##
" c         s  s   |  ] } | d  Vq d S(   i    N(    (   t   .0R   (    (    s   renpy/memory.pys	   <genexpr>Ÿ   s    c         s  s   |  ] } | d  Vq d S(   i   N(    (   RG   R   (    (    s   renpy/memory.pys	   <genexpr>    s    c         3  s5   |  ]+ } | d  ˆ  k r | d ˆ k r | Vq d S(   i   i    N(    (   RG   R   (   t   leavest   roots(    s   renpy/memory.pys	   <genexpr>¨   s    s   Cycle:i    s     s    -i   t   =i   (   t   setR   t   TrueR   R-   t   remove(   R;   t   namet   leftt   rightt   edgeR   t   relevant(    (   RC   RH   RD   RE   RI   RF   s   renpy/memory.pyt   cycle_finderD   s2    	R	

#	
-c         C  s^  | d k r i  } n  g  } t j t ƒ } d „  } xO |  D]G \ } } t | ƒ } | | k rd q: n  | | | <| j | | f ƒ q: Wt j } t j	 }	 | j }
 t
 j t
 j t
 j f } x™ | rS| j d ƒ \ } } t | | ƒ rë q» n  | | c | | ƒ 7<xL |	 | ƒ D]> } t | ƒ } | | k r2qn  | | | <|
 | | f ƒ qWq» W| | f S(   s»  
    Walks over memory, trying to account it to the objects in `roots`. Each
    object in memory is attributed to at most one of the roots. We use a
    breadth-first search to try to come up with the most accurate
    attribution possible.

    `roots`
        A list of (name, object) tuples.

    Returns a dictionary mapping names to the number of bytes
    reachable from that name, and a dictionary mapping object ids to
    names.
    c         S  s   d S(   s=   
        Adds o to the worklist if it's not in seen.
        N(    (   RN   R;   (    (    s   renpy/memory.pyR!   Õ   s    i    N(   R   t   collectionst   defaultdictR#   R    t   appendR   t	   getsizeofR   t   get_referentsR%   R'   R(   t   FunctionTypet   popR"   (   RI   t   seent   worklistt   sizeR!   RN   R;   t   id_oRW   RX   t   worklist_appendt   ignore_typesRA   t   id_v(    (    s   renpy/memory.pyt   walk_memory¼   s6    		
				
t   renpyt   storec         C  sã   g  } xÐ t  t j j ƒ  ƒ D]¹ \ } } | d k r: q n  x$ |  D] } | j | ƒ rA PqA qA Wq | j d ƒ p| | j d ƒ s… q n  | j d ƒ rš q n  x8 | j j ƒ  D]' \ } } | j | d | | f ƒ qª Wq Wt | ƒ S(   sæ   
    Profiles object, surface, and texture memory used in the renpy and store
    packages.

    Returns a map from name to the number of bytes accounted for by that
    name, and a dictionary mapping object ids to
    names.
    Rc   Rd   s   renpy.storeR   N(	   t   sortedR   t   modulest   itemsR   t
   startswitht   __dict__RV   Rb   (   t   packagesRI   t   mod_namet   modt   pRN   R;   (    (    s   renpy/memory.pyt   profile_memory_commonþ   s    
"#g      ð?i    c   	      C  s  t  d d ƒ t  d ƒ t  d t j ƒ  d ƒ t  d ƒ g  t ƒ  d j ƒ  D] \ } } | | f ^ qN } | j ƒ  t d „  | Dƒ ƒ } | } xZ | D]R \ } } | | | |  k  rá | | k rá t  d j | | ƒ ƒ qá n  | | 8} q™ Wt  d ƒ t  d j | ƒ ƒ t  d ƒ d S(   s  
    :doc: memory

    Profiles object, surface, and texture memory use by Ren'Py and the
    game. Writes an accounting of memory use by to the memory.txt file and
    stdout.

    The accounting is by names in the store and in the Ren'Py implementation
    that the memory is reachable from. If an object is reachable from more
    than one name, it's assigned to the name it's most directly reachable
    from.

    `fraction`
        The fraction of the total memory usage to show. 1.0 will show all
        memory usage, .9 will show the top 90%.

    `minimum`
        If a name is accounted less than `minimum` bytes of memory, it will
        not be printed.

    As it has to scan all memory used by Ren'Py, this function may take a
    long time to complete.
    RJ   iN   R   s   Memory profile at t   :i    c         s  s   |  ] } | d  Vq d S(   i    N(    (   RG   R   (    (    s   renpy/memory.pys	   <genexpr>C  s    s
   {:13,d} {}t   -i   sC   {:13,d} Total object, surface, and texture memory usage (in bytes).Ns   -------------(   R   t   timet   ctimeRn   Rg   t   sortt   sumR   (	   t   fractiont   minimumR@   RA   t   usaget   totalt	   remainingR]   RN   (    (    s   renpy/memory.pyt   profile_memory!  s     

2

c         C  sF  t  d d ƒ t  d ƒ t  d t j ƒ  d ƒ t  d ƒ t ƒ  d } t | j ƒ  ƒ } g  } x= | j ƒ  D]/ \ } } | j | t j	 | d ƒ | f ƒ ql W| j
 ƒ  xL | D]D \ } } | d k rÎ q° n  | r° t  d j | | | | ƒ ƒ q° q° Wt  d d ƒ t  d j | t | d ƒ ƒ t  d ƒ |  rB| a | a n  d S(   sA  
    :doc: memory

    Profiles objects, surface, and texture memory use by Ren'Py and the game.
    Writes (to memory.txt and stdout) the difference in memory usage from the
    last time this function was called with `update` true.

    The accounting is by names in the store and in the Ren'Py implementation
    that the memory is reachable from. If an object is reachable from more
    than one name, it's assigned to the name it's most directly reachable
    from.

    As it has to scan all memory used by Ren'Py, this function may take a
    long time to complete.
    RJ   iN   R   s   Memory diff at Ro   i    s   renpy.memory.old_usages   {:+14,d} {:13,d} {}Rp   i   t    i   s   Total memory usage (in bytes).Ns   --------------s   -------------- s   -------------(   R   Rq   Rr   Rn   Rt   t   valuesR7   RV   t	   old_usageR   Rs   R   t	   old_total(   t   updateRw   Rx   t   diffR@   RA   t   changeRN   (    (    s   renpy/memory.pyt   diff_memoryY  s.    


$
c          C  s¼  t  d d ƒ t  d ƒ t  d t j ƒ  d ƒ t  d ƒ t d d g ƒ d }  i  } t t j j j ƒ } | j ƒ  g  } x/| D]'} xŒ | j	 j
 ƒ  D]{ \ } } xl | j
 ƒ  D]^ \ } } | d	 | }	 t | ƒ }
 |
 |  k rü |
 | k rü |	 | |
 <n  | j |	 | f ƒ q± Wq˜ Wx` | j D]U \ } } t | ƒ }
 d
 }	 | j |
 |	 ƒ }	 |  j |
 |	 ƒ }	 | j |	 | f ƒ q!W| j d | j j f ƒ | j d | j f ƒ q‚ Wt | |  ƒ d } g  | j
 ƒ  D] \ } } | | f ^ qÍ} | j ƒ  t  d j d ƒ d d j d ƒ ƒ t  d d d d d ƒ xU | D]M \ } }	 |	 j d ƒ r[q:n  | r:t  d j | | t | ƒ |	 ƒ ƒ q:q:Wt  d ƒ t  d j t | ƒ ƒ ƒ t  d ƒ d S(   s   
    :doc: memory

    Profiles memory used by the rollback system. Writes (to memory.txt and
    stdout) the memory used by the rollback system. This tries to account
    for rollback memory used by various store variables, as well as by
    internal aspects of the rollback system.
    RJ   iN   R   s   Rollback profile at Ro   Rd   s   renpy.displayi   R   s	   <unknown>s   <scene lists>s	   <context>i    s   Total Bytesi   R{   s   Per RollbackRp   i2   Rc   s   {:13,d} {:13,d} {}s   {} Rollback objects exist.Ns   -------------s   ------------- s   -------------(   R   Rq   Rr   Rn   R-   Rc   t   gamet   logt   reverset   storesR7   R    RV   t   objectsR   t   contextt   scene_listsRb   Rs   t   rjustRh   R   R   (   R[   t   new_seenR„   RI   t   rbt
   store_nameRd   t   var_nameR;   RN   R^   t   rollt   sizesR@   RA   Rw   R]   (    (    s   renpy/memory.pyt   profile_rollbackŽ  sL    



+
$*
c           s   t  j ƒ  t  j ƒ  ‰  ‡  f d †  } xc ˆ  D][ } t | |  ƒ r, d d l } | j ƒ  d k  r‡ t ƒ  t d ƒ t ƒ  | | ƒ q‡ q, q, Wd S(   s:   
    Finds the parents of every object of type `cls`.
    c   
        s@  d } t  ƒ  } g  } g  } xt d ƒ D]} | j |  ƒ t | t t |  ƒ ƒ t |  ƒ d d ƒyC t |  t ƒ r– d |  k r– t d |  d ƒ n t t	 |  ƒ ƒ Wn t d ƒ n Xt
 } t |  t j ƒ rõ | sÝ Pn  | j ƒ  \ }  } q( n  t |  t j ƒ rpxf |  j j ƒ  D]R \ } } | | d k r| ƒ  } | j t | ƒ ƒ | j | | d	 f ƒ qqWn  x– t j |  ƒ D]… }	 |	 ˆ  k s€|	 | k r¤q€n  t |	 ƒ | k r¼q€n  t |	 t j ƒ rÔq€n  | j t |	 ƒ ƒ | j |	 | d
 f ƒ t } Pq€W| sPn  | s&t d ƒ n  | j ƒ  \ }  } q( Wd  S(   NR   i   t   endR{   R/   s	   with names	   Bad repr.iüÿÿÿs    (key) s     s   <no parent, popping>(   RK   t   rangeRV   R   R)   R    R5   R"   R0   R   t   FalseR%   R'   RZ   t   weakreft   WeakKeyDictionaryt   dataRg   R!   R   t   get_referrerst	   FrameTypeRL   (
   R;   R   R[   t   queueR‡   t   _it   foundR@   RA   R   (   t   objs(    s   renpy/memory.pyt
   print_pathä  sR    	)	!iÿÿÿÿNgš™™™™™¹?s3   ===================================================(   R   t   collectt   get_objectsR"   t   randomR   (   t   clsRž   R;   R¡   (    (   R   s   renpy/memory.pyt   find_parentsÚ  s    
>
(   t
   __future__R    Rq   R•   R%   R   RT   R   R
   Rc   R„   t   openR   R   R   RS   R   Rb   Rn   Rz   R}   R~   RL   R‚   R‘   R£   (    (    (    s   renpy/memory.pyt   <module>   s(   			xB#45	L