zoukankan      html  css  js  c++  java
  • 关于linux 内存碎片指数

    linux针对每一个node的每个zone的每个order,都有一个碎片指数来描述当前的碎片程度,也就是

    extfrag_index 参数:
    extfrag_index这个要展示出来,需要内核编译了两个选项,即:

    #if defined(CONFIG_DEBUG_FS) && defined(CONFIG_COMPACTION)
    否则不会生成这个文件。
    [root@localhost ~]#    grep CONFIG_DEBUG_FS /boot/config-3.10.0-693.5.2.el7.x86_64 
    CONFIG_DEBUG_FS=y
    [root@localhost ~]# grep CONFIG_COMPACTION /boot/config-3.10.0-693.5.2.el7.x86_64 
    CONFIG_COMPACTION=y

    如果确定已经编译进入内核,但是也看不到/sys/kernel/debug/下的数据,那说明没有挂载,或者挂载的路径不是/sys/kernel/debug/,如果没有挂载则需要挂载一下:

    mount -t debugfs none  /sys/kernel/debug

    然后,在linux里面展示如下:

    [root@localhost ~]# cat /sys/kernel/debug/extfrag/extfrag_index
    Node 0, zone      DMA -1.000 -1.000 -1.000 -1.000 -1.000 -1.000 -1.000 -1.000 -1.000 -1.000 -1.000 
    Node 0, zone    DMA32 -1.000 -1.000 -1.000 -1.000 -1.000 -1.000 -1.000 -1.000 -1.000 -1.000 -1.000 
    Node 0, zone   Normal -1.000 -1.000 -1.000 -1.000 -1.000 -1.000 -1.000 -1.000 -1.000 0.995 0.998 
    Node 1, zone   Normal -1.000 -1.000 -1.000 -1.000 -1.000 -1.000 -1.000 -1.000 0.988 0.994 0.997 

    那这些数据怎么理解呢?

    我们先来看一下打印这些数据的函数:

    static void extfrag_show_print(struct seq_file *m,
                        pg_data_t *pgdat, struct zone *zone)
    {
        unsigned int order;
        int index;
    
        /* Alloc on stack as interrupts are disabled for zone walk */
        struct contig_page_info info;
    
        seq_printf(m, "Node %d, zone %8s ",
                    pgdat->node_id,
                    zone->name);
        for (order = 0; order < MAX_ORDER; ++order) {
            fill_contig_page_info(zone, order, &info);
            index = __fragmentation_index(order, &info);
            seq_printf(m, "%d.%03d ", index / 1000, index % 1000);------------可以看出,"."前面是__fragmentation_index返回值的除数,后面是余数 
    }
    seq_putc(m,
    ' ');
    }

    如下就是计算碎片指数的函数:

    static int __fragmentation_index(unsigned int order, struct contig_page_info *info)
    {
        unsigned long requested = 1UL << order;
    
        if (!info->free_blocks_total)------------没有内存,返回0,都没有内存,谈何碎片
            return 0;
    
        /* Fragmentation index only makes sense when a request would fail */
        if (info->free_blocks_suitable)------------返回-1000,也就是展示的是-1.000,那么这个时候没有意义,因为内存充足,不关心碎片指数,碎片指数只在申请内存失败的时候有意义
            return -1000;
    
        /*
         * Index is between 0 and 1 so return within 3 decimal places
         *
         * 0 => allocation would fail due to lack of memory
         * 1 => allocation would fail due to fragmentation
         */
        return 1000 - div_u64( (1000+(div_u64(info->free_pages * 1000ULL, requested))), info->free_blocks_total);
    }

    可以看出,越靠近1000,则碎片越严重,很容易分配失败。-1000表示内存充足,不需要关心碎片指数。为0代表压根就没free内存了,也不需要关心碎片指数。这两个极端都不需要考虑。

    我们来看具体的数据:

    [root@localhost ~]# cat /proc/buddyinfo 
    Node 0, zone      DMA      0      1      1      1      1      1      1      0      1      1      3 
    Node 0, zone    DMA32    187    276    194    232    133     43      7      6      2      2    178 
    Node 0, zone   Normal 108231  75779  17645   6950   3437   1991   1100    297      1      0      0 
    Node 1, zone   Normal  77511  40265   9424   7355   4124   2210    950      2      0      0      0 
    [root@localhost ~]# cat /sys/kernel/debug/extfrag/extfrag_index
    Node 0, zone      DMA -1.000 -1.000 -1.000 -1.000 -1.000 -1.000 -1.000 -1.000 -1.000 -1.000 -1.000 
    Node 0, zone    DMA32 -1.000 -1.000 -1.000 -1.000 -1.000 -1.000 -1.000 -1.000 -1.000 -1.000 -1.000 
    Node 0, zone   Normal -1.000 -1.000 -1.000 -1.000 -1.000 -1.000 -1.000 -1.000 -1.000 0.995 0.998 
    Node 1, zone   Normal -1.000 -1.000 -1.000 -1.000 -1.000 -1.000 -1.000 -1.000 0.988 0.994 0.997

    然后迁移合并一下内存:

    [root@localhost ~]# echo 1 >/proc/sys/vm/compact_memory 
    [root@localhost ~]# cat /proc/buddyinfo                 
    Node 0, zone      DMA      0      1      1      1      1      1      1      0      1      1      3 
    Node 0, zone    DMA32    563    489    286    211    100     39      7      6      2      1    178 
    Node 0, zone   Normal  19109   8235   5752   6181   3805   2486   1572    704    266    127     42 
    Node 1, zone   Normal  22730  11342   7692   8589   5944   3296   1300     93     26      5      0 
    [root@localhost
    ~]# cat /sys/kernel/debug/extfrag/extfrag_index Node 0, zone DMA -1.000 -1.000 -1.000 -1.000 -1.000 -1.000 -1.000 -1.000 -1.000 -1.000 -1.000 Node 0, zone DMA32 -1.000 -1.000 -1.000 -1.000 -1.000 -1.000 -1.000 -1.000 -1.000 -1.000 -1.000 Node 0, zone Normal -1.000 -1.000 -1.000 -1.000 -1.000 -1.000 -1.000 -1.000 -1.000 -1.000 -1.000 Node 1, zone Normal -1.000 -1.000 -1.000 -1.000 -1.000 -1.000 -1.000 -1.000 -1.000 -1.000 0.993
    总的来看,当有最后一个大页的内存的时候,即4k*2的10次方,也就是4M的连续页面的时候,问题都不大,因为可以拆分页面。

    所以如果需要脚本判断当前系统的碎片程度,可以看最后4列的值,如果都为-1.000,没问题,否则多少存在碎片,如果值越大,则越碎。

    可以通过配置cat /proc/sys/vm/extfrag_threshold来缓解碎片的问题。这个值默认是500.
    如果超过了extfrag_threshold这个值, kswapd就会触发memory compaction . 所以, 这个值设置接近1000, 说明系统在内存碎片的处理倾向于把旧的页换出, 以符合申请的需要; 而设置接近0, 表示系统在内存碎片的处理倾向于做memory compaction,迁移合并及时的话,就可以缓解碎片。但迁移合并是耗性能的,所以可以将其配置为200左右。
    水平有限,如果有错误,请帮忙提醒我。如果您觉得本文对您有帮助,可以点击下面的 推荐 支持一下我。版权所有,需要转发请带上本文源地址,博客一直在更新,欢迎 关注 。
  • 相关阅读:
    SQLServer: 解决“错误15023:当前数据库中已存在用户或角色
    DEV界面皮肤
    模拟业务最小测试用例
    POJ 2503 Babelfish(map)
    POJ 2001 Shortest Prefixes
    洛谷 P2672 推销员
    POJ 2104 K-th Number && 洛谷 P3834 【模板】可持久化线段树 1(主席树)
    洛谷 P1589 泥泞路
    HDU 6183 Color it(动态开点线段树)
    POJ 2482 Stars in Your Window
  • 原文地址:https://www.cnblogs.com/10087622blog/p/8543792.html
Copyright © 2011-2022 走看看