/proc/meminfo 中的 MemAvailable 有多准确?

/proc/meminfo 中的 MemAvailable 有多准确?

虽然之前已经有人问过MemFree和之间的区别(MemAvailable/proc/meminfo 中的 MemFree 和 MemAvailable 有什么区别)、答案和文章(例如https://topic.alibabacloud.com/a/the-difference-between-linux-memfree-and-memavailable_1_16_30151791.html) 总是表示这MemAvailable是一个估计值。这似乎意味着存在一定的不准确性MemAvailable

有人可以解释一下为什么它是一个估计值,不准确性在哪里以及有多大,以及是否MemAvailable倾向于低估或高估可用内存?

答案1

来自页面分配.c从下面的源代码中,你可以看到计算的估计部分是可以释放多少比例的页面缓存和可回收的 slab 内存而不会导致交换。在这两种情况下,/proc/zoneinfo假设至少需要一半(如果更多,则需要低水位线)。

因此,每个“不准确性”的极限只能在低水位和假设之间全部可以被释放,但这显然不是事实。

一半(而不是 1/4 或 3/4)是否合理取决于你的系统和使用情况 - 从原始提交

这是错误的,因为 Cached 包含不能作为页面缓存释放的内存,例如共享内存段、tmpfs 和 ramfs,并且它不包含可回收的 slab 内存,这些内存会在大多数具有大量文件的空闲系统上占用大量系统内存。

在此Unix 和 Linux问题,如何才能跨发行版获取可用内存量?,评论表明计算得出的值比读取的值更大,/proc/meminfo但这并不总是正确的。

long si_mem_available(void)
{
    long available;
    unsigned long pagecache;
    unsigned long wmark_low = 0;
    unsigned long pages[NR_LRU_LISTS];
    unsigned long reclaimable;
    struct zone *zone;
    int lru;

    for (lru = LRU_BASE; lru < NR_LRU_LISTS; lru++)
        pages[lru] = global_node_page_state(NR_LRU_BASE + lru);

    for_each_zone(zone)
        wmark_low += low_wmark_pages(zone);

    /*
     * Estimate the amount of memory available for userspace allocations,
     * without causing swapping.
     */
    available = global_zone_page_state(NR_FREE_PAGES) - totalreserve_pages;

    /*
     * Not all the page cache can be freed, otherwise the system will
     * start swapping. Assume at least half of the page cache, or the
     * low watermark worth of cache, needs to stay.
     */
    pagecache = pages[LRU_ACTIVE_FILE] + pages[LRU_INACTIVE_FILE];
    pagecache -= min(pagecache / 2, wmark_low);
    available += pagecache;

    /*
     * Part of the reclaimable slab and other kernel memory consists of
     * items that are in use, and cannot be freed. Cap this estimate at the
     * low watermark.
     */
    reclaimable = global_node_page_state(NR_SLAB_RECLAIMABLE) +
            global_node_page_state(NR_KERNEL_MISC_RECLAIMABLE);
    available += reclaimable - min(reclaimable / 2, wmark_low);

    if (available < 0)
        available = 0;
    return available;
}
EXPORT_SYMBOL_GPL(si_mem_available);

相关内容