
    &`i8                        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
 d dlmZmZ d dlmZmZmZmZ d dlmZ  e j        e          Zd	eeef         d
eeef         deeef         fdZdefdee         defdZ G d d          ZdS )    N)Counter)reduce)DictList)PlacementGroupTableData)*AUTOSCALER_MAX_RESOURCE_DEMAND_VECTOR_SIZE!AUTOSCALER_REPORT_PER_NODE_STATUS)	DictCountLoadMetricsSummaryNodeIPResourceDict)PlacementStrategydict1dict2returnc                     |                                  }|                                D ]!\  }}||                    |d          z   ||<   "|S )zqAdd the values in two dictionaries.

    Returns:
        dict: A new dictionary (inputs remain unmodified).
    r   )copyitemsget)r   r   new_dictkvs        x/home/jaya/work/projects/VOICE-AGENT/VIET/agent-env/lib/python3.11/site-packages/ray/autoscaler/_private/load_metrics.pyadd_resourcesr      sO     zz||H - -1(,,q!,,,O    dictsc                     d t          fd| D                       }g }|                                D ]%\  }}|                     ||          |f           &|S )a$  Count a list of dictionaries (or unhashable types).

    This is somewhat annoying because mutable data structures aren't hashable,
    and set/dict keys must be hashable.

    Args:
        dicts (List[D]): A list of dictionaries to be counted.
        serializer (D -> S): A custom serialization function. The output type S
            must be hashable. The default serializer converts a dictionary into
            a frozenset of KV pairs.
        deserializer (S -> U): A custom deserialization function. See the
            serializer for information about type S. For dictionaries U := D.

    Returns:
        List[Tuple[U, int]]: Returns a list of tuples. Each entry in the list
            is a tuple containing a unique entry from `dicts` and its
            corresponding frequency count.
    Nc                 D    t          |                                           S N)	frozensetr   )ds    r   <lambda>zfreq_of_dicts.<locals>.<lambda>7   s    y33 r   c              3   .   K   | ]} |          V  d S r    ).0r!   
serializers     r   	<genexpr>z freq_of_dicts.<locals>.<genexpr>9   s+      11aJJqMM111111r   )r   r   append)r   r&   deserializerfreqsas_listas_setcounts    `     r   freq_of_dictsr.   #   s~    & 33
1111511111EG 6 6V,,e45555Nr   c                   6   e Zd ZdZd Zd Z	 	 	 ddededeeef         deeef         d	e	d
e
eee	f                  de
eee	f                  de
e         fdZd Zde
e         fdZd Zdeeef         fdZd Zd Zd dZd Zd ZdefdZd Zd Zd Zd ZdS )!LoadMetricszContainer for cluster load metrics.

    Metrics here are updated from raylet heartbeats. The autoscaler
    queries these metrics to determine when to scale up, and which nodes
    can be removed.
    c                     i | _         i | _        i | _        i | _        g | _        g | _        g | _        g | _        i | _        d S r   )	last_heartbeat_time_by_ipstatic_resources_by_ipdynamic_resources_by_ipnode_id_by_ipwaiting_bundlesinfeasible_bundlespending_placement_groupsresource_requestsray_nodes_last_used_time_by_ipselfs    r   __init__zLoadMetrics.__init__H   sP    )+&&(#')$!"$(*%!#.0+++r   c                 *    t          | j                  S )zA load metrics instance is Falsey iff the autoscaler process
        has not received a resource message from the GCS.
        )boolr5   r;   s    r   __bool__zLoadMetrics.__bool__S   s     D&'''r   Nipnode_idstatic_resourcesdynamic_resourcesnode_idle_duration_sr6   r7   r8   c	                 \   || j         |<   || j        |<   |sg }|sg }|sg }|                                }	| j         |                                         D ]\  }
}|
|	vrd|	|
<   |	| j        |<   t          j                    }||z
  | j        |<   || j        |<   || _        || _	        || _
        d S )N        )r3   r5   r   r   r4   timer:   r2   r6   r7   r8   )r<   rA   rB   rC   rD   rE   r6   r7   r8   dynamic_resources_updateresource_namecapacitynows                r   updatezLoadMetrics.updateY   s     +;#B'!(2 	! O! 	$!#' 	*')$ $5#9#9#;#; '+'B2'F'L'L'N'N 	> 	>#M8$<<<:=(7+C$R(ikk258L2L+B/-0&r*."4(@%%%r   c                     |
J d            t                               d                    |                     t          j                    | j        |<   d S )NzIP should be known at this timez*Node {} is newly setup, treating as active)loggerdebugformatrH   r2   )r<   rA   s     r   mark_activezLoadMetrics.mark_active   sL    ~~@~~~AHHLLMMM-1Y[[&r***r   
active_ipsc                     t                    fd} || j        d            || j        d            || j        d            || j        d            || j        d           dS )a  The Raylet ips stored by LoadMetrics are obtained by polling
        the GCS in Monitor.update_load_metrics().

        On the other hand, the autoscaler gets a list of node ips from
        its NodeProvider.

        This method removes from LoadMetrics the ips unknown to the autoscaler.

        Args:
            active_ips (List[str]): The node ips known to the autoscaler.
        c                 $   t          |           z
  }|D ]%}|rt                              d| d           | |= &|r>|r<t                              d                    t	          |          |                     |t          |           z  rJ d S )NzLoadMetrics: Removed ip: .z7LoadMetrics: Removed {} stale ip mappings: {} not in {})setrO   inforQ   len)mapping
should_logunwanted_ipsunwanted_iprS   s       r   prunez+LoadMetrics.prune_active_ips.<locals>.prune   s    w<<*4L+ ) ) OKK M{ M M MNNNK(( 
 AAGL))<B B   %s7||344444r   T)r[   FN)rW   r:   r3   r5   r4   r2   )r<   rS   r^   s    ` r   prune_active_ipszLoadMetrics.prune_active_ips   s     __
	5 	5 	5 	5 	5 	d1dCCCCd)e<<<<d U3333d*u====d,??????r   c                 4    | j                                         S )ad  Return a list of node resources (static resource sizes).

        Example:
            >>> from ray.autoscaler._private.load_metrics import LoadMetrics
            >>> metrics = LoadMetrics(...) # doctest: +SKIP
            >>> metrics.get_node_resources() # doctest: +SKIP
            [{"CPU": 1}, {"CPU": 4, "GPU": 8}]  # for two different nodes
        )r3   valuesr;   s    r   get_node_resourceszLoadMetrics.get_node_resources   s     *11333r   r   c                     | j         S )ah  Return a dict of node resources for every node ip.

        Example:
            >>> from ray.autoscaler._private.load_metrics import LoadMetrics
            >>> metrics = LoadMetrics(...)  # doctest: +SKIP
            >>> metrics.get_static_node_resources_by_ip()  # doctest: +SKIP
            {127.0.0.1: {"CPU": 1}, 127.0.0.2: {"CPU": 4, "GPU": 8}}
        )r3   r;   s    r   get_static_node_resources_by_ipz+LoadMetrics.get_static_node_resources_by_ip   s     **r   c                     | j         S r   )r4   r;   s    r   get_resource_utilizationz$LoadMetrics.get_resource_utilization   s    ++r   c                 0   i }i }| j                                         D ]u\  }}| j        |         }|                                D ]N\  }}|||         z
  }||vr
d||<   d||<   ||xx         |z  cc<   ||xx         |z  cc<   t          d|          }Ov||fS )NrG   r   )r3   r   r4   max)	r<   resources_usedresources_totalrA   max_resourcesavail_resourcesresource_idamountuseds	            r   _get_resource_usagezLoadMetrics._get_resource_usage   s    !%!<!B!B!D!D 		$ 		$B":2>O'4':':'<'< $ $#V <<n4425N;/36OK0{+++t3+++,,,6,,,1d||$ ..r   Tc                 v    |r)| j         d t                   | j        d t                   z   S | j         | j        z   S r   )r6   r   r7   )r<   clips     r   get_resource_demand_vectorz&LoadMetrics.get_resource_demand_vector   sO     
	B $%P&P%PQ)*U+U*UVW
 '$*AAAr   c                     | j         S r   )r9   r;   s    r   get_resource_requestsz!LoadMetrics.get_resource_requests   s    %%r   c                     | j         S r   )r8   r;   s    r   get_pending_placement_groupsz(LoadMetrics.get_pending_placement_groups   s    ,,r   c                    | j         r,t          t          | j                                                   ni }d                    t          |                    dd                              }d|v r+|d                    t          |d                             z  }d|v r+|d                    t          |d                             z  }|S )zqReturn a concise string of cluster size to report to event logs.

        For example, "3 CPUs, 4 GPUs".
        z{} CPUsCPUr   GPUz	, {} GPUsTPUz	, {} TPUs)r3   r   r   ra   rQ   intr   )r<   total_resourcesouts      r   resources_avail_summaryz#LoadMetrics.resources_avail_summary   s     *F=$"="D"D"F"FGGG 	
 s?#6#6ua#@#@AABBO##;%%c/%*@&A&ABBBCO##;%%c/%*@&A&ABBBC
r   c                    | j         r,t          t          | j                                                   ni }| j        r,t          t          | j                                                  ni }i }|D ]9}|dv r||         }||         }||z
  |f||<   !||         }|||         z
  |f||<   :t          |                     d                    }t          |                                           }d }	d }
t          |                                 |	|
          }t          | j                                                  }d }t          ri }| j        
                                D ]c\  }}| j                             |i           }i ||<   |
                                D ])\  }}||                    |d          z
  |f||         |<   *dt          ||||||          S )	N)memoryobject_store_memoryF)rr   c                 P    t          d | j        D                       }|| j        fS )Nc              3   b   K   | ]*}t          |j                                                  V  +d S r   )r    unit_resourcesr   )r%   bundles     r   r'   zJLoadMetrics.summary.<locals>.placement_group_serializer.<locals>.<genexpr>  sJ        =C	&/557788     r   )tuplebundlesstrategy)pgr   s     r   placement_group_serializerz7LoadMetrics.summary.<locals>.placement_group_serializer  s>      GIz    G R[))r   c                     t          t          t          | d                             }t          |          t	          j        | d                   dS )Nr      )r   r   )listmapdictr.   r   Name)pg_tupler   s     r   placement_group_deserializerz9LoadMetrics.summary.<locals>.placement_group_deserializer  sK    
 3tXa[1122G(11-28A;??  r   )r&   r)   r   )usageresource_demand	pg_demandrequest_demand
node_typesusage_by_node)r4   r   r   ra   r3   r.   rs   ru   rw   r	   r   r   r   )r<   available_resourcesr}   
usage_dictkeytotal	availablesummarized_demand_vectorsummarized_resource_requestsr   r   summarized_placement_groupsnodes_summaryr   rA   totalsresources                    r   summaryzLoadMetrics.summary   sP    +F=$">"E"E"G"GHHH 	 *F=$"="D"D"F"FGGG 	
 
" 	L 	LC777',/4	#(9#4e"<
3',#(+>s+C#CU"K
3#0+++77$
 $
  (5T5O5O5Q5Q'R'R$	* 	* 	*		 		 		 '4--//15'
 '
 '
#
 &d&A&H&H&J&JKK, 		M"9??AA  
F 8<<RDD	$&b!'-||~~  OHe	h : ::3M"%h// "417$'
 
 
 	
r   c                 j    |t          |t                    s
J |            d |D             | _        d S )Nc                 8    g | ]}t          |          d k    |S )r   )rY   )r%   requests     r   
<listcomp>z5LoadMetrics.set_resource_requests.<locals>.<listcomp>>  s/     "
 "
 "
#g,,:J:JG:J:J:Jr   )
isinstancer   r9   )r<   requested_resourcess     r   set_resource_requestsz!LoadMetrics.set_resource_requests;  sO    *1488MM:MMM8"
 "
#6"
 "
 "
r   c                     dd                     d t          |                                                                           D                       z   S )Nz - z
 - c                 @    g | ]\  }}d                      ||          S )z{}: {})rQ   )r%   r   r   s      r   r   z+LoadMetrics.info_string.<locals>.<listcomp>D  s*    LLLtq!X__Q""LLLr   )joinsorted_infor   r;   s    r   info_stringzLoadMetrics.info_stringB  sL    w||LLvdjjll6H6H6J6J/K/KLLL
 
 
 	
r   c                    |                                  \  t          j                    fd| j                                        D             }fd| j                                        D             }t          | j                                        d           d d         }fd|D             }d d                    fd	t                    D                       d
                    |rt          t          |                    nd|r9t          t          t          |                    t          |          z            nd|rt          t          |                    nd          d
                    |rt          t          |                    nd|r9t          t          t          |                    t          |          z            nd|rt          t          |                    nd          |dS )Nc                     g | ]}|z
  S r$   r$   r%   trL   s     r   r   z%LoadMetrics._info.<locals>.<listcomp>K  s    TTT!cAgTTTr   c                     g | ]}|z
  S r$   r$   r   s     r   r   z%LoadMetrics._info.<locals>.<listcomp>L  s    TTTq37TTTr   c                     | d         S )Nr   r$   )pairs    r   r"   z#LoadMetrics._info.<locals>.<lambda>N  s
    T!W r   )r      c                 "    i | ]\  }}||z
  S r$   r$   )r%   rA   r   rL   s      r   
<dictcomp>z%LoadMetrics._info.<locals>.<dictcomp>P  s#    "V"V"VUR2a"V"V"Vr   c                 v    | dv r&d                     t          |dz  d                    S t          |d          S )N)r   r   z{} GiBi   @   )rQ   round)r   values     r   format_resourcez*LoadMetrics._info.<locals>.format_resourceR  s>    777uU6H-I1'M'MNNNUA&r   z, c           
          g | ]N}|                     d           d                     ||                    ||                   |          OS )znode:z{}/{} {})
startswithrQ   )r%   ridr   rj   ri   s     r   r   z%LoadMetrics._info.<locals>.<listcomp>Z  sx        >>'22%%'^C-@AA'_S-ABB   r   zMin={} Mean={} Max={})ResourceUsageNodeIdleSecondsTimeSinceLastHeartbeatMostDelayedHeartbeats)rp   rH   r:   ra   r2   r   r   r   rQ   r|   minfloatsumrY   rh   )r<   
idle_timesheartbeat_timesmost_delayed_heartbeatsr   rL   rj   ri   s       @@@@r   r   zLoadMetrics._infoG  s<   *.*B*B*D*D'ikkTTTTt'J'Q'Q'S'STTT
TTTTD,J,Q,Q,S,STTT"(*00228L8L#
 #
 #

1"# #W"V"V"V>U"V"V"V	' 	' 	' "YY       &n55  
 
  7==(2:C
OO$$$AKSE#j//**S__<===QS(2:C
OO$$$   
 '>&D&D-<DC(()))""E#o..//#o2F2FFGGG-<DC(()))"' ' &=1
 
 	
r   )NNN)T)__name__
__module____qualname____doc__r=   r@   strbytesr   r   r   r   rM   rR   r_   rb   r   r   rd   rf   rp   rs   ru   rw   r   r   r   r   r   r$   r   r   r0   r0   @   s        	1 	1 	1( ( ( 3759BF$A $A$A $A sDy/	$A
  T	?$A $$A d3:./$A !c5j!12$A #''>"?$A $A $A $AL9 9 9
!@49 !@ !@ !@ !@F	4 	4 	4	+fl6J1K 	+ 	+ 	+ 	+, , ,/ / / B B B B& & &- - -    "E
 E
 E
N
 
 

 
 

*
 *
 *
 *
 *
r   r0   )loggingrH   collectionsr   	functoolsr   typingr   r   ray._private.gcs_utilsr   !ray.autoscaler._private.constantsr   r	   ray.autoscaler._private.utilr
   r   r   r   ray.core.generated.common_pb2r   	getLoggerr   rO   r   r   r   r   r.   r0   r$   r   r   <module>r      s                         : : : : : :                   < ; ; ; ; ;		8	$	$	c5j) 	$sEz2B 	tCQVJGW 	 	 	 	 154  d I    :q
 q
 q
 q
 q
 q
 q
 q
 q
 q
r   