免费注册 查看新帖 |

Chinaunix

  平台 论坛 博客 文库
最近访问板块 发新帖
查看: 2664 | 回复: 8
打印 上一主题 下一主题

[内存管理] page zone 分配策略如何理解 [复制链接]

论坛徽章:
11
未羊
日期:2013-12-16 12:45:4615-16赛季CBA联赛之青岛
日期:2016-04-11 19:17:4715-16赛季CBA联赛之广夏
日期:2016-04-06 16:34:012015亚冠之卡尔希纳萨夫
日期:2015-11-10 10:04:522015亚冠之大阪钢巴
日期:2015-07-30 18:29:402015亚冠之城南
日期:2015-06-15 17:56:392015亚冠之卡尔希纳萨夫
日期:2015-05-15 15:19:272015亚冠之山东鲁能
日期:2015-05-14 12:38:13金牛座
日期:2014-12-04 15:34:06子鼠
日期:2014-10-16 13:40:4715-16赛季CBA联赛之八一
日期:2016-07-22 09:41:40
跳转到指定楼层
1 [收藏(0)] [报告]
发表于 2012-08-06 14:33 |只看该作者 |倒序浏览

  1. struct zonelist {
  2.     struct zone *zones[MAX_NUMNODES * MAX_NR_ZONES + 1]; // NULL delimited
  3. };

  4. typedef struct pglist_data {
  5.     struct zone node_zones[MAX_NR_ZONES];
  6.     struct zonelist node_zonelists[MAX_ZONELISTS];
  7.     int nr_zones;
  8. #ifdef CONFIG_FLAT_NODE_MEM_MAP    /* means !SPARSEMEM */
  9.     struct page *node_mem_map;
  10. #ifdef CONFIG_CGROUP_MEM_RES_CTLR
  11.     struct page_cgroup *node_page_cgroup;
  12. #endif
  13. #endif
  14. #ifndef CONFIG_NO_BOOTMEM
  15.     struct bootmem_data *bdata;
  16. #endif
  17. #ifdef CONFIG_MEMORY_HOTPLUG
  18.     /*
  19.          * Must be held any time you expect node_start_pfn, node_present_pages
  20.          * or node_spanned_pages stay constant.  Holding this will also
  21.          * guarantee that any pfn_valid() stays that way.
  22.          *
  23.          * Nests above zone->lock and zone->size_seqlock.
  24.          */
  25.     spinlock_t node_size_lock;
  26. #endif
  27.     unsigned long node_start_pfn;
  28.     unsigned long node_present_pages; /* total number of physical pages */
  29.     unsigned long node_spanned_pages; /* total size of physical page
  30.                                              range, including holes */
  31.     int node_id;
  32.     wait_queue_head_t kswapd_wait;
  33.     struct task_struct *kswapd;
  34.     int kswapd_max_order;
  35.     enum zone_type classzone_idx;
  36. } pg_data_t;


复制代码
如上的 pglist_data 结构, 一直以为 node_zones 和 node_zonelists 关系如下:
node_zones 是实际上的 zone 结构, 每个 pglist_data 存在最多三个 zone
node_zonelists 代表分配策略, node_zonelists 是 zonelist 数组, 每个zonelist 又是 zone 的一个链表;
因此形成如下的关系:
pglist_data_0 = {
    .node_zones = {.node_zones = {zone_0_dma, zone_0_normal, zone_0_high},}
    .node_zonelists = {.zones = {&zone_0_high, &zone_1_high, &zone_0_normal, &zone_1_normal, 0}}
}

pglist_data_0 = {
    .node_zones = {.node_zones = {zone_1_dma, zone_1_normal, zone_1_high},}
    .node_zonelists = {.zones = {&zone_1_high, &zone_0_high, &zone_1_normal, &zone_0_normal, 0}}
}

但看以下代码有点傻眼:
  1. static unsigned int nr_free_zone_pages(int offset)
  2. {
  3.     pg_data_t *pgdat;
  4.     unsigned int sum = 0;

  5.     for_each_pgdat(pgdat) {
  6.         struct zonelist *zonelist = pgdat->node_zonelists + offset;
  7.         struct zone **zonep = zonelist->zones;
  8.         struct zone *zone;

  9.         for (zone = *zonep++; zone; zone = *zonep++) {
  10.             unsigned long size = zone->present_pages;
  11.             unsigned long high = zone->pages_high;
  12.             if (size > high)
  13.                 sum += size - high;
  14.         }
  15.     }

  16.     return sum;
  17. }
复制代码
如果按照我的理解, 很显然 sum 值是实际值的2倍, 因为计算 pglist_data_0 时其实将 zone_1_high, zone_1_normal 也计算进去了, pglist_data_1 时同理将 zone_0_high, zone_0_normal 计算进去了

不知实际上node_zones 和 node_zonelists 关系到底是什么样的

论坛徽章:
0
2 [报告]
发表于 2012-08-14 17:11 |只看该作者
node_zones 是pglist里面的所包含对zone, node_zonelists是分配时的优先级链。例如:对于 某个zonelist: zone1->zone2->zone3, 分配zone1内存时,如果在zone1上分配失败,再去zone2上分配,依次向后。
对node_zonelists source code 上的注释很清楚:
* One allocation request operates on a zonelist. A zonelist
* is a list of zones, the first one is the 'goal' of the
* allocation, the other zones are fallback zones, in decreasing
* priority.

论坛徽章:
11
未羊
日期:2013-12-16 12:45:4615-16赛季CBA联赛之青岛
日期:2016-04-11 19:17:4715-16赛季CBA联赛之广夏
日期:2016-04-06 16:34:012015亚冠之卡尔希纳萨夫
日期:2015-11-10 10:04:522015亚冠之大阪钢巴
日期:2015-07-30 18:29:402015亚冠之城南
日期:2015-06-15 17:56:392015亚冠之卡尔希纳萨夫
日期:2015-05-15 15:19:272015亚冠之山东鲁能
日期:2015-05-14 12:38:13金牛座
日期:2014-12-04 15:34:06子鼠
日期:2014-10-16 13:40:4715-16赛季CBA联赛之八一
日期:2016-07-22 09:41:40
3 [报告]
发表于 2012-08-14 17:38 |只看该作者
George_lz 发表于 2012-08-14 17:11
node_zones 是pglist里面的所包含对zone, node_zonelists是分配时的优先级链。例如:对于 某个zonelist:  ...


非所问。

论坛徽章:
0
4 [报告]
发表于 2012-08-14 18:22 |只看该作者
回复 3# zylthinking

理解错了。
我用的35上的代码刚好解除了你的疑问:
static unsigned int nr_free_zone_pages(int offset)
{
        struct zoneref *z;
        struct zone *zone;

        /* Just pick one node, since fallback list is circular */
        unsigned int sum = 0;

        struct zonelist *zonelist = node_zonelist(numa_node_id(), GFP_KERNEL);

        for_each_zone_zonelist(zone, z, zonelist, offset) {
                unsigned long size = zone->present_pages;
                unsigned long high = high_wmark_pages(zone);
                if (size > high)
                        sum += size - high;
        }

        return sum;
}

   

论坛徽章:
11
未羊
日期:2013-12-16 12:45:4615-16赛季CBA联赛之青岛
日期:2016-04-11 19:17:4715-16赛季CBA联赛之广夏
日期:2016-04-06 16:34:012015亚冠之卡尔希纳萨夫
日期:2015-11-10 10:04:522015亚冠之大阪钢巴
日期:2015-07-30 18:29:402015亚冠之城南
日期:2015-06-15 17:56:392015亚冠之卡尔希纳萨夫
日期:2015-05-15 15:19:272015亚冠之山东鲁能
日期:2015-05-14 12:38:13金牛座
日期:2014-12-04 15:34:06子鼠
日期:2014-10-16 13:40:4715-16赛季CBA联赛之八一
日期:2016-07-22 09:41:40
5 [报告]
发表于 2012-08-14 23:08 |只看该作者
George_lz 发表于 2012-08-14 18:22
回复 3# zylthinking

理解错了。


为什么解除了? 我还是感觉照样

论坛徽章:
0
6 [报告]
发表于 2012-08-15 10:44 |只看该作者
回复 5# zylthinking


Don't feel confusing, it's just a bug.
The following is the information for this commit.



commit e310fd43256b3cf4d37f6447b8f7413ca744657a
Author: Martin J. Bligh <mbligh@mbligh.org>
Date:   Fri Jul 29 22:59:18 2005 -0700

    [PATCH] Fix NUMA node sizing in nr_free_zone_pages
   
    We are iterating over all nodes in nr_free_zone_pages().  Because the
    fallback zonelists contain all nodes in the system, and we walk all the
    zonelists, we're counting memory multiple times (once for each node).  This
    caused us to make a size estimate of 32GB for an 8GB AMD64 box, which makes
    all the dirty ratio calculations, etc incorrect.
   
    There's still a further bug to fix from e820 holes causing overestimation
    as well, but this fix is separate, and good as is, and fixes one class of
    problems.  Problem found by Badari, and tested by Ram Pai - thanks!
   
    Signed-off-by:  Martin J. Bligh <mbligh@mbligh.org>
    Signed-off-by:  Matt Dobson <colpatch@us.ibm.com>
    Signed-off-by: Andrew Morton <akpm@osdl.org>
    Signed-off-by: Linus Torvalds <torvalds@osdl.org>

diff --git a/mm/page_alloc.c b/mm/page_alloc.c
index 42bccfb..8d08837 100644
--- a/mm/page_alloc.c
+++ b/mm/page_alloc.c
@@ -1061,20 +1061,19 @@ unsigned int nr_free_pages_pgdat(pg_data_t *pgdat)

static unsigned int nr_free_zone_pages(int offset)
{
-        pg_data_t *pgdat;
+        /* Just pick one node, since fallback list is circular */
+        pg_data_t *pgdat = NODE_DATA(numa_node_id());
        unsigned int sum = 0;

-        for_each_pgdat(pgdat) {
-                struct zonelist *zonelist = pgdat->node_zonelists + offset;
-                struct zone **zonep = zonelist->zones;
-                struct zone *zone;
+        struct zonelist *zonelist = pgdat->node_zonelists + offset;
+        struct zone **zonep = zonelist->zones;
+        struct zone *zone;

-                for (zone = *zonep++; zone; zone = *zonep++) {
-                        unsigned long size = zone->present_pages;
-                        unsigned long high = zone->pages_high;
-                        if (size > high)
-                                sum += size - high;
-                }
+        for (zone = *zonep++; zone; zone = *zonep++) {
+                unsigned long size = zone->present_pages;
+                unsigned long high = zone->pages_high;
+                if (size > high)
+                        sum += size - high;
        }

        return sum;

论坛徽章:
11
未羊
日期:2013-12-16 12:45:4615-16赛季CBA联赛之青岛
日期:2016-04-11 19:17:4715-16赛季CBA联赛之广夏
日期:2016-04-06 16:34:012015亚冠之卡尔希纳萨夫
日期:2015-11-10 10:04:522015亚冠之大阪钢巴
日期:2015-07-30 18:29:402015亚冠之城南
日期:2015-06-15 17:56:392015亚冠之卡尔希纳萨夫
日期:2015-05-15 15:19:272015亚冠之山东鲁能
日期:2015-05-14 12:38:13金牛座
日期:2014-12-04 15:34:06子鼠
日期:2014-10-16 13:40:4715-16赛季CBA联赛之八一
日期:2016-07-22 09:41:40
7 [报告]
发表于 2012-08-15 22:02 |只看该作者
那就知道了, 3.x 的变化比如 fallback list 缩减成一个 这些我也知道, 因此 3.x 上我也没觉得有问题, 就是之前的代码让我很迷惑。
话说找到这些 commit 有什么窍门么, 经常看到一些人拿出 commit commence 来说事, 但找到这些 commence 莫不是有什么技巧? 我的意思是说, 除了 git 那个二分查找搜索某个改变在哪个commit引入的命令

论坛徽章:
16
2015亚冠之吉达阿赫利
日期:2015-08-17 11:21:462015年迎新春徽章
日期:2015-03-04 09:58:11酉鸡
日期:2014-12-07 09:06:19水瓶座
日期:2014-11-04 14:23:29天秤座
日期:2014-03-02 08:57:52双鱼座
日期:2014-02-22 13:07:56午马
日期:2014-02-14 11:08:18双鱼座
日期:2014-02-13 11:09:37卯兔
日期:2014-02-06 15:10:34子鼠
日期:2014-01-20 14:48:19戌狗
日期:2013-12-19 09:37:46射手座
日期:2013-12-19 09:33:47
8 [报告]
发表于 2012-08-15 22:05 |只看该作者
建议楼上大哥直接看最新代码,

论坛徽章:
16
2015亚冠之吉达阿赫利
日期:2015-08-17 11:21:462015年迎新春徽章
日期:2015-03-04 09:58:11酉鸡
日期:2014-12-07 09:06:19水瓶座
日期:2014-11-04 14:23:29天秤座
日期:2014-03-02 08:57:52双鱼座
日期:2014-02-22 13:07:56午马
日期:2014-02-14 11:08:18双鱼座
日期:2014-02-13 11:09:37卯兔
日期:2014-02-06 15:10:34子鼠
日期:2014-01-20 14:48:19戌狗
日期:2013-12-19 09:37:46射手座
日期:2013-12-19 09:33:47
9 [报告]
发表于 2012-08-15 22:06 |只看该作者
git log --grep='nr_free_zone_pages'
您需要登录后才可以回帖 登录 | 注册

本版积分规则 发表回复

  

北京盛拓优讯信息技术有限公司. 版权所有 京ICP备16024965号-6 北京市公安局海淀分局网监中心备案编号:11010802020122 niuxiaotong@pcpop.com 17352615567
未成年举报专区
中国互联网协会会员  联系我们:huangweiwei@itpub.net
感谢所有关心和支持过ChinaUnix的朋友们 转载本站内容请注明原作者名及出处

清除 Cookies - ChinaUnix - Archiver - WAP - TOP