perf(debug): 内存监控增强为 100ms 采样 + 多维度指标
- 采样间隔从 1s 降到 100ms,spike 阈值降到 50MB - 增加 uss/shared/private/data/dirty/compressed 等指标 - 更贴近 macOS 活动监视器'内存'列的统计口径
This commit is contained in:
parent
faef998a9a
commit
2b131de702
@ -93,11 +93,40 @@ def _current_vms_mb() -> Optional[float]:
|
|||||||
return None
|
return None
|
||||||
|
|
||||||
|
|
||||||
def get_memory_info() -> Dict[str, Optional[float]]:
|
def _get_detailed_memory_info() -> Dict[str, Optional[float]]:
|
||||||
return {
|
"""获取更详细的内存指标,更接近 macOS 活动监视器。"""
|
||||||
|
result: Dict[str, Optional[float]] = {
|
||||||
"rss_mb": _current_rss_mb(),
|
"rss_mb": _current_rss_mb(),
|
||||||
"vms_mb": _current_vms_mb(),
|
"vms_mb": _current_vms_mb(),
|
||||||
|
"uss_mb": None,
|
||||||
|
"shared_mb": None,
|
||||||
|
"private_mb": None,
|
||||||
|
"data_mb": None,
|
||||||
|
"dirty_mb": None,
|
||||||
|
"compressed_mb": None,
|
||||||
}
|
}
|
||||||
|
try:
|
||||||
|
import psutil
|
||||||
|
proc = psutil.Process()
|
||||||
|
info = proc.memory_info()
|
||||||
|
# uss 只在 memory_full_info() 中提供
|
||||||
|
try:
|
||||||
|
full = proc.memory_full_info()
|
||||||
|
result["uss_mb"] = getattr(full, "uss", None) / (1024 * 1024) if getattr(full, "uss", None) else None
|
||||||
|
result["compressed_mb"] = getattr(full, "compressed", None) / (1024 * 1024) if getattr(full, "compressed", None) else None
|
||||||
|
except Exception:
|
||||||
|
pass
|
||||||
|
result["shared_mb"] = getattr(info, "shared", None) / (1024 * 1024) if getattr(info, "shared", None) else None
|
||||||
|
result["private_mb"] = getattr(info, "private", None) / (1024 * 1024) if getattr(info, "private", None) else None
|
||||||
|
result["data_mb"] = getattr(info, "data", None) / (1024 * 1024) if getattr(info, "data", None) else None
|
||||||
|
result["dirty_mb"] = getattr(info, "dirty", None) / (1024 * 1024) if getattr(info, "dirty", None) else None
|
||||||
|
except Exception:
|
||||||
|
pass
|
||||||
|
return result
|
||||||
|
|
||||||
|
|
||||||
|
def get_memory_info() -> Dict[str, Optional[float]]:
|
||||||
|
return _get_detailed_memory_info()
|
||||||
|
|
||||||
|
|
||||||
def _estimate_text_size(text: Any) -> int:
|
def _estimate_text_size(text: Any) -> int:
|
||||||
@ -247,20 +276,21 @@ class TopAllocator:
|
|||||||
|
|
||||||
|
|
||||||
def _periodic_sampling(
|
def _periodic_sampling(
|
||||||
interval_seconds: float = 1.0,
|
interval_seconds: float = 0.1,
|
||||||
spike_threshold_mb: float = 100.0,
|
spike_threshold_mb: float = 50.0,
|
||||||
max_records: int = 3,
|
max_records: int = 10,
|
||||||
) -> None:
|
) -> None:
|
||||||
"""后台线程:每秒采样一次内存,发现快速增长或峰值时记录。"""
|
"""后台线程:每 100ms 采样一次内存,发现快速增长或峰值时记录。"""
|
||||||
global _last_sample_rss_mb, _peak_rss_mb
|
global _last_sample_rss_mb, _peak_rss_mb
|
||||||
records_since_spike = 0
|
records_since_spike = 0
|
||||||
|
last_regular_log = 0.0
|
||||||
while ENABLED:
|
while ENABLED:
|
||||||
try:
|
try:
|
||||||
info = get_memory_info()
|
info = get_memory_info()
|
||||||
rss = info.get("rss_mb")
|
rss = info.get("rss_mb")
|
||||||
vms = info.get("vms_mb")
|
|
||||||
if rss is not None:
|
if rss is not None:
|
||||||
spike = False
|
spike = False
|
||||||
|
delta = None
|
||||||
if _last_sample_rss_mb is not None:
|
if _last_sample_rss_mb is not None:
|
||||||
delta = rss - _last_sample_rss_mb
|
delta = rss - _last_sample_rss_mb
|
||||||
if delta >= spike_threshold_mb:
|
if delta >= spike_threshold_mb:
|
||||||
@ -271,19 +301,16 @@ def _periodic_sampling(
|
|||||||
records_since_spike -= 1
|
records_since_spike -= 1
|
||||||
log_memory_event(
|
log_memory_event(
|
||||||
"memory_periodic_spike",
|
"memory_periodic_spike",
|
||||||
rss_mb=rss,
|
**info,
|
||||||
vms_mb=vms,
|
delta_from_last_mb=delta,
|
||||||
peak_rss_mb=_peak_rss_mb,
|
|
||||||
delta_from_last_mb=(delta if spike else None),
|
|
||||||
)
|
)
|
||||||
else:
|
else:
|
||||||
# 每 5 秒记录一次常规采样,避免日志过多
|
now = time.time()
|
||||||
if int(time.time()) % 5 == 0:
|
if now - last_regular_log >= 2.0:
|
||||||
|
last_regular_log = now
|
||||||
log_memory_event(
|
log_memory_event(
|
||||||
"memory_periodic_sample",
|
"memory_periodic_sample",
|
||||||
rss_mb=rss,
|
**info,
|
||||||
vms_mb=vms,
|
|
||||||
peak_rss_mb=_peak_rss_mb,
|
|
||||||
)
|
)
|
||||||
except Exception:
|
except Exception:
|
||||||
pass
|
pass
|
||||||
@ -291,8 +318,8 @@ def _periodic_sampling(
|
|||||||
|
|
||||||
|
|
||||||
def start_periodic_sampling(
|
def start_periodic_sampling(
|
||||||
interval_seconds: float = 1.0,
|
interval_seconds: float = 0.1,
|
||||||
spike_threshold_mb: float = 100.0,
|
spike_threshold_mb: float = 50.0,
|
||||||
) -> None:
|
) -> None:
|
||||||
"""启动后台内存采样线程。幂等:重复调用不会启动多个线程。"""
|
"""启动后台内存采样线程。幂等:重复调用不会启动多个线程。"""
|
||||||
global _sample_thread
|
global _sample_thread
|
||||||
|
|||||||
Loading…
Reference in New Issue
Block a user