|
""" |
|
Memory management utilities for efficient-context. |
|
""" |
|
|
|
import logging |
|
import gc |
|
import os |
|
import psutil |
|
from typing import Optional, Dict, Any |
|
from contextlib import contextmanager |
|
|
|
|
|
logging.basicConfig(level=logging.INFO) |
|
logger = logging.getLogger(__name__) |
|
|
|
class MemoryManager: |
|
""" |
|
Manages memory usage for efficient context handling. |
|
|
|
This class provides utilities to monitor and optimize memory usage |
|
when working with large language models and context on CPU. |
|
""" |
|
|
|
def __init__( |
|
self, |
|
target_usage_percent: float = 80.0, |
|
aggressive_cleanup: bool = False, |
|
memory_monitor_interval: Optional[float] = None, |
|
): |
|
""" |
|
Initialize the MemoryManager. |
|
|
|
Args: |
|
target_usage_percent: Target memory usage as percentage of available memory |
|
aggressive_cleanup: Whether to perform aggressive garbage collection |
|
memory_monitor_interval: Interval for memory monitoring in seconds (None to disable) |
|
""" |
|
self.target_usage_percent = target_usage_percent |
|
self.aggressive_cleanup = aggressive_cleanup |
|
self.memory_monitor_interval = memory_monitor_interval |
|
self.monitor_active = False |
|
|
|
logger.info( |
|
"MemoryManager initialized with target usage: %.1f%%", |
|
target_usage_percent |
|
) |
|
|
|
def get_memory_usage(self) -> Dict[str, Any]: |
|
""" |
|
Get current memory usage statistics. |
|
|
|
Returns: |
|
stats: Dictionary of memory usage statistics |
|
""" |
|
|
|
process = psutil.Process(os.getpid()) |
|
process_memory = process.memory_info() |
|
|
|
|
|
system_memory = psutil.virtual_memory() |
|
|
|
|
|
process_percent = (process_memory.rss / system_memory.total) * 100 |
|
system_percent = system_memory.percent |
|
|
|
return { |
|
"process_rss_bytes": process_memory.rss, |
|
"process_vms_bytes": process_memory.vms, |
|
"process_percent": process_percent, |
|
"system_available_bytes": system_memory.available, |
|
"system_total_bytes": system_memory.total, |
|
"system_used_percent": system_percent, |
|
} |
|
|
|
def log_memory_usage(self) -> None: |
|
"""Log memory usage statistics.""" |
|
stats = self.get_memory_usage() |
|
|
|
logger.info( |
|
"Memory usage: Process: %.1f%% (%.1f MB), System: %.1f%% (%.1f GB available)", |
|
stats["process_percent"], |
|
stats["process_rss_bytes"] / (1024 * 1024), |
|
stats["system_used_percent"], |
|
stats["system_available_bytes"] / (1024 * 1024 * 1024) |
|
) |
|
|
|
def cleanup_memory(self) -> None: |
|
"""Perform memory cleanup.""" |
|
|
|
collected = gc.collect() |
|
|
|
if self.aggressive_cleanup: |
|
|
|
collected += gc.collect() |
|
|
|
logger.debug("Memory cleanup: Collected %d objects", collected) |
|
|
|
def _check_memory_threshold(self) -> bool: |
|
""" |
|
Check if memory usage exceeds the target threshold. |
|
|
|
Returns: |
|
exceeded: Whether the threshold is exceeded |
|
""" |
|
stats = self.get_memory_usage() |
|
return stats["system_used_percent"] > self.target_usage_percent |
|
|
|
@contextmanager |
|
def optimize_memory(self): |
|
""" |
|
Context manager for optimizing memory during operations. |
|
|
|
Example: |
|
``` |
|
with memory_manager.optimize_memory(): |
|
# Run memory-intensive operations |
|
``` |
|
""" |
|
|
|
if logger.isEnabledFor(logging.DEBUG): |
|
self.log_memory_usage() |
|
|
|
try: |
|
|
|
yield |
|
finally: |
|
|
|
if self._check_memory_threshold(): |
|
logger.info("Memory threshold exceeded, performing cleanup") |
|
self.cleanup_memory() |
|
|
|
|
|
if logger.isEnabledFor(logging.DEBUG): |
|
self.log_memory_usage() |
|
|