我知道 malloc_trim 在 linux 上工作,window 上有类似的功能吗?
您在这里比较苹果和橙子。
std::unordered_map
是一个更高级别的容器,它内部的某个地方使用 new
和 delete
C++ 运算符来分配和释放内存。 这些运算符在内部可能会也可能不会碰巧依赖 libc malloc
,但您不能对此做出任何假设。然而 malloc_trim
是 libc 的 GNU 扩展。
如果正在使用的 C++ 运行时通过
malloc
进行分配,那么 malloc_trim
也将在这里工作。
要问的正确问题是:是否有针对常用 C++ 运行时的特定于供应商的扩展,这些扩展对
new
/delete
的作用相当于 malloc_trim
对 Glibc malloc
的作用?
无论哪种方式,真正的问题是:你为什么关心?在进程的整个生命周期中,经过一定的“预热”期后,典型分配器实现的内存区域的active大小很可能会稳定下来,并且接近最佳大小正在运行的程序。另请记住,arena 的虚拟内存映射的大小可能比实际物理映射的大小大得多。在 64 位机器上完全有可能拥有数百 TB 的虚拟集大小,但实际驻留集中只有几千字节。
SetProcessWorkingSetSizeEx(pid, SIZE_T(-1), SIZE_T(-1), QUOTA_LIMITS_HARDWS_MIN_DISABLE)似乎是答案。
这是我用来最终在与大熊猫 DataFrame 密切配合的 Python 进程中修剪 RAM 的跨平台 trim_ram() 解决方案:
import gc
import ctypes
import ctypes.wintypes
import platform,
import logging
logger = logging.getLogger(__name__)
def trim_windows_process_memory(pid: int = None) -> bool:
"""Causes effect similar to malloc_trim on -nix."""
# Define SIZE_T based on the platform (32-bit or 64-bit)
if ctypes.sizeof(ctypes.c_void_p) == 4:
SIZE_T = ctypes.c_uint32
else:
SIZE_T = ctypes.c_uint64
# Get a handle to the current process
if not pid:
pid = ctypes.windll.kernel32.GetCurrentProcess()
# Define argument and return types for SetProcessWorkingSetSizeEx
ctypes.windll.kernel32.SetProcessWorkingSetSizeEx.argtypes = [
ctypes.wintypes.HANDLE, # Process handle
SIZE_T, # Minimum working set size
SIZE_T, # Maximum working set size
ctypes.wintypes.DWORD, # Flags
]
ctypes.windll.kernel32.SetProcessWorkingSetSizeEx.restype = ctypes.wintypes.BOOL
# Define constants for SetProcessWorkingSetSizeEx
QUOTA_LIMITS_HARDWS_MIN_DISABLE = 0x00000002
# Attempt to set the working set size
result = ctypes.windll.kernel32.SetProcessWorkingSetSizeEx(pid, SIZE_T(-1), SIZE_T(-1), QUOTA_LIMITS_HARDWS_MIN_DISABLE)
if result == 0:
# Retrieve the error code
error_code = ctypes.windll.kernel32.GetLastError()
logger.error(f"SetProcessWorkingSetSizeEx failed with error code: {error_code}")
return False
else:
return True
def trim_ram() -> None:
"""Forces python garbage collection.
Most importantly, calls malloc_trim/SetProcessWorkingSetSizeEx, which fixes pandas/libc (?) memory leak."""
gc.collect()
if platform.system() == "Windows":
trim_windows_process_memory()
else:
try:
ctypes.CDLL("libc.so.6").malloc_trim(0)
except Exception as e:
logger.error("malloc_trim attempt failed")
我确信您会弄清楚如何从 C++ 本地调用 SetProcessWorkingSetSizeEx。