免费注册 查看新帖 |

Chinaunix

  平台 论坛 博客 文库
12下一页
最近访问板块 发新帖
查看: 4120 | 回复: 12

[内存管理] 在看页缓存回收相关代码时遇到一个疑问,请教大家讨论 [复制链接]

论坛徽章:
0
发表于 2013-01-07 17:34 |显示全部楼层
众所周知linux对块设备脏页设置有如下两个参数:
1. /proc/sys/vm/dirty_background_ratio
2. /proc/sys/vm/dirty_ratio

对2.6.29内核,对以上两个参数的实现原理,我做了如下的分析。
     在对块设备写入数据时,会调用balance_dirty_pages_ratelimited()判断是否需要脏页回收。
balance_dirty_pages_ratelimited() -> balance_dirty_pages_ratelimited_nr -> balance_dirty_pages();
最后实现脏页处理的函数在banalce_dirty_pages中。分析此函数发现,dirty_background_ratio 很好理解,就是内存中的脏页大于设置的这个比例,就启动后台pdflush刷写数据。
if ((laptop_mode && pages_written) ||
                        (!laptop_mode && (global_page_state(NR_FILE_DIRTY)
                                          + global_page_state(NR_UNSTABLE_NFS)
                                          > background_thresh)))
                pdflush_operation(background_writeout, 0);

但是dirty_ratio参数的作用看起来稍微复杂一些,get_dirty_limits()中会做如下计算:
        dirty = (dirty_ratio * available_memory) / 100;
              /*
                 * Calculate this BDI's share of the dirty ratio.
                 */
                bdi_writeout_fraction(bdi, &numerator, &denominator);

                bdi_dirty = (dirty * (100 - bdi_min_ratio)) / 100;
                bdi_dirty *= numerator;
                do_div(bdi_dirty, denominator);
以上计算,会根据bdi_writeout_fraction计算一个分数,dirty乘以这个分数算出,这个bdi可以占用内存的比例。

static void bdi_writeout_fraction(struct backing_dev_info *bdi,
                long *numerator, long *denominator)
{
        if (bdi_cap_writeback_dirty(bdi)) {
                prop_fraction_percpu(&vm_completions, &bdi->completions,
                                numerator, denominator);
        } else {
                *numerator = 0;
                *denominator = 1;
        }
}

/*
* Obtain a fraction of this proportion
*
*   p_{j} = x_{j} / (period/2 + t % period/2)
*/
void prop_fraction_percpu(struct prop_descriptor *pd,
                struct prop_local_percpu *pl,
                long *numerator, long *denominator)
{
        struct prop_global *pg = prop_get_global(pd);
        unsigned long period_2 = 1UL << (pg->shift - 1);
        unsigned long counter_mask = period_2 - 1;
        unsigned long global_count;

        prop_norm_percpu(pg, pl);
        *numerator = percpu_counter_read_positive(&pl->events);

        global_count = percpu_counter_read(&pg->events);
        *denominator = period_2 + (global_count & counter_mask);

        prop_put_global(pd, pg);
}

现在的问题是,这个分数的分子分母是怎么计算的,为什么这么计算,有什么好处,基于什么考虑的?
我分析的代码,觉得这么计算的原理是根据这个设备一段时间的流量,与系统总io流量的比例进行计算。
此处代码的思想是流量大的设备可以多占用系统缓存资源。流量小的设备,不允许占用太多缓存资源。防止资源浪费。

不知道我的理解是否正确,请大家拍砖。

论坛徽章:
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
发表于 2013-01-07 17:55 |显示全部楼层
本帖最后由 embeddedlwp 于 2013-01-07 17:55 编辑

回复 1# 25641463

我分析的代码,觉得这么计算的原理是根据这个设备一段时间的流量,与系统总io流量的比例进行计算。
此处代码的思想是流量大的设备可以多占用系统缓存资源。流量小的设备,不允许占用太多缓存资源。防止资源浪费。


可以这么理解!
   

论坛徽章:
0
发表于 2013-01-07 19:04 |显示全部楼层
这块周期计算公式不知道是怎么确定的,为什么这么确定。而且这个计算方式貌似问题也很多。3.0后的内核版本邮件列表中也对一些问题进行了修复。我认为此处研究的价值还是很大的。
http://thread.gmane.org/gmane.linux.kernel.mm/68826

论坛徽章:
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
发表于 2013-01-08 09:48 |显示全部楼层
see git log

论坛徽章:
2
CU十二周年纪念徽章
日期:2013-10-24 15:41:34处女座
日期:2013-12-27 22:22:41
发表于 2013-01-08 23:58 |显示全部楼层
> 此处代码的思想是流量大的设备可以多占用系统缓存资源。流量小的设备,不允许占用太多缓存资源。防止资源浪费。

我当年看代码的理解是,单个设备的阈值与设备回写能力成正比,写得快的就放宽,写得慢的就紧缩点。快慢动态定义,取决于一个设备近期的表现,那时似乎有个积分函数,给设备历史回写表现与近期回写表现分配权比,算出一个值表现其回写能力。当时Wu的一个patch就是改变了一个系数,让这个值更快地收敛。

现在已经开始显式测量回写速度了。看代码里的注释和图解,比我那时看的更加复杂了。

论坛徽章:
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
发表于 2013-01-09 08:37 |显示全部楼层
恩,是这样的。各个bdi device是share系统的writeback bandwidth的,每结束写回一个page,就会对相应的bdi增加completion count,然后根据一段时间内本bdi device的count与系统的count的比值来分享系统的bandwidth,如果这个bdi device最近有大量的writeback,他会被认为是一个fast device,会share到比较大的bandwidth,体现在bdi threshold上。

论坛徽章:
0
发表于 2013-01-10 15:48 |显示全部楼层
本帖最后由 25641463 于 2013-01-10 15:50 编辑

最近几个版本的内核此处的注释好长。。。。。可能计算公式又复杂了,基本几行代码就会一堆注释,而且函数头还有插图。。真心越来越深奥

论坛徽章:
0
发表于 2013-02-01 15:25 |显示全部楼层
最近找到了2007年的patch解释。。。
不知道老外的高等数学里p_{j} = \Sum_{i=0} (dx_{j}/dt_{-i}) / 2^(1+i)
\这个斜杠是什么符号。。。。

http://lwn.net/Articles/245603/

论坛徽章:
1
拜羊年徽章
日期:2015-03-03 16:15:43
发表于 2013-02-01 20:31 来自手机 |显示全部楼层
\不是高等数学的符号。c语言里的换行符。

论坛徽章:
2
CU十二周年纪念徽章
日期:2013-10-24 15:41:34处女座
日期:2013-12-27 22:22:41
发表于 2013-02-02 23:34 |显示全部楼层
本帖最后由 tempname2 于 2013-02-02 23:35 编辑

\sum在Latex里是求和符号。
您需要登录后才可以回帖 登录 | 注册

本版积分规则 发表回复

  

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

清除 Cookies - ChinaUnix - Archiver - WAP - TOP