如何在windows上回收c++ unordered_map的内存

问题描述 投票:0回答:2

我知道 malloc_trim 在 linux 上工作,window 上有类似的功能吗?

stl unordered-map
2个回答
0
投票

您在这里比较苹果和橙子。

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 的虚拟集大小,但实际驻留集中只有几千字节。


0
投票

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。

© www.soinside.com 2019 - 2024. All rights reserved.