Linux 内核 delayacct 原理分析

源码基于:Linux5.10

约定:

  • 芯片架构:ARM64
  • 内存架构:UMA
  • CONFIG_ARM64_VA_BITS:39
  • CONFIG_ARM64_PAGE_SHIFT:12
  • CONFIG_PGTABLE_LEVELS :3

1. 使用

内核需要使能:

CONFIG_TASK_DELAY_ACCT=y
CONFIG_TASKSTATS=y

启动参数中默认是使能的,可以在启动参数中添加 nodelayacct 来disable,截止 5.10 版本都是通过该参数进行 disable。

最新的版本也可以通过 sysctl 的 kernel.task_delayacct 进行开关。

当使能 CONFIG_TASK_DELAY_ACCT 时,在 struct task_struct 中会多个成员:

struct task_struct {
         ...   

#ifdef CONFIG_TASK_DELAY_ACCT
        struct task_delay_info                *delays;
#endif
        ...
}

在系统启动后,可以使用 getdelays命令来访问指定的 pid 或 tgid 的task:

shift:/ # getdelays -d -p 25348 -v
print delayacct stats ON
debug on
family id 26
Sent pid/tgid, retval 0
received 380 bytes
nlmsghdr size=16, nlmsg_len=380, rep_len=380
PID     25348


CPU             count     real total  virtual total    delay total  delay average
                 1126      779761825      752721329      944603556          0.839ms
IO              count    delay total  delay average
                  201      660349228              3ms
SWAP            count    delay total  delay average
                    0              0              0ms
RECLAIM         count    delay total  delay average
                   10       56215518              5ms
THRASHING       count    delay total  delay average
                   57      326115261              5ms

getdelays 命令将dealyacct 分成了几个维度:

  • CPU
  • IO
  • SWAP
  • RECLAIM
  • THRASHING

2. struct task_delay_info

include/linux/delayacct.h

#ifdef CONFIG_TASK_DELAY_ACCT
struct task_delay_info {
        raw_spinlock_t        lock;
        unsigned int        flags;        /* Private per-task flags */

        /* For each stat XXX, add following, aligned appropriately
         *
         * struct timespec XXX_start, XXX_end;
         * u64 XXX_delay;
         * u32 XXX_count;
         *
         * Atomicity of updates to XXX_delay, XXX_count protected by
         * single lock above (split into XXX_lock if contention is an issue).
         */

        /*
         * XXX_count is incremented on every XXX operation, the delay
         * associated with the operation is added to XXX_delay.
         * XXX_delay contains the accumulated delay time in nanoseconds.
         */
        u64 blkio_start;        /* Shared by blkio, swapin */
        u64 blkio_delay;        /* wait for sync block io completion */
        u64 swapin_delay;        /* wait for swapin block io completion */
        u32 blkio_count;        /* total count of the number of sync block */
                                /* io operations performed */
        u32 swapin_count;        /* total count of the number of swapin block */
                                /* io operations performed */

        u64 freepages_start;
        u64 freepages_delay;        /* wait for memory reclaim */

        u64 thrashing_start;
        u64 thrashing_delay;        /* wait for thrashing page */

        u32 freepages_count;        /* total count of memory reclaim */
        u32 thrashing_count;        /* total count of thrash waits */
};
#endif
  • lock:同步锁,用于保护结构体;
  • flags:用于标识任务阻塞的原因,DELAYACCT_PF_SWAPIN 和 DELAYACCT_PF_BLKIO,分别表示处于swapin 状态和等IO 状态;
  • blkio_start:swapin、io 公用,记录开始的时间点,单位 ns;
  • blkio_delay:task 等待 IO 资源而阻塞的时长,单位 ns,详细看 __schedule() 和 try_to_wake_up() 函数;
  • swapin_delay:swapin 耗时,单位 ns,详细看 do_swap_page() 函数;
  • blkio_count:task 等待 IO 资源而阻塞的次数;
  • swapin_count:swapin 次数;
  • freepages_start:内存回收的开始时间点,单位 ns,详细查看 do_try_to_free_pages();
  • feepages_delay:内存回收耗时,单位 ns,详细查看 do_try_to_free_pages();
  • freepages_count:内存回收的次数;
  • thrashing_start:页面抖动的起始时间点,单位 ns,详细查看 wait_on_page_bit_common();
  • thrashing_delay:页面抖动时长,单位ns,详细查看 wait_on_page_bit_common();
  • thrashing_count:页面抖动次数;

2.1 IO 耗时统计

在主调度函数 __schedule() 中会检测 task_struct 中 in_iowait 这个变量,如果为 true 表示调度在等待 IO 资源,此时会调用 delayacct_blkio_start() 开始计时,并将其存放在 blkio_start 中。

当 IO 资源可用时,该阻塞task 会被唤醒,进而会调用 delayacct_blkio_end() 结束计时。此函数中会统计blkio_delay 和 blkio_count。

kernel/sched/core.c

static void __sched notrace __schedule(bool preempt)
{
        ...
                        if (prev->in_iowait) {
                                atomic_inc(&rq->nr_iowait);
                                delayacct_blkio_start();
                        }
        ...
}

static int
try_to_wake_up(struct task_struct *p, unsigned int state, int wake_flags)
{
        ...
        cpu = select_task_rq(p, p->wake_cpu, SD_BALANCE_WAKE, wake_flags);
        if (task_cpu(p) != cpu) {
                if (p->in_iowait) {
                        delayacct_blkio_end(p);
                        atomic_dec(&task_rq(p)->nr_iowait);
                }
                ...
        }
        ...
}

另外,有一种情况,这个等待 IO 资源是page fault 时需要 swapin,此时会将结构体中 flags 标志加上(或运算) DELAYACCT_PF_SWAPIN,用以统计此次 swapin 的耗时,当成功获得IO 资源后,此次 IO 耗时会被统计到 swapin_delay 里,而不被统计到 blkio_delay。即 blkio_delay 统计的是非swapin 的IO 耗时,而 swapin_delay 统计的是 swapin 的 IO 耗时。

mm/memory.c

vm_fault_t do_swap_page(struct vm_fault *vmf)
{
        ...
        delayacct_set_flag(DELAYACCT_PF_SWAPIN);
        page = lookup_swap_cache(entry, vma, vmf->address);
        swapcache = page;
        
        ...
        locked = lock_page_or_retry(page, vma->vm_mm, vmf->flags);

        delayacct_clear_flag(DELAYACCT_PF_SWAPIN);
        ...
}

2.2 reclaim 耗时统计

在内存紧张时会进行内存回收,最终会调用到 do_try_to_free_pages() 函数,这里会统计整个回收过程所产生的耗时(调用 shrink_zones 函数)。

mm/vmscan.c

static unsigned long do_try_to_free_pages(struct zonelist *zonelist,
                                          struct scan_control *sc)
{
        ...
retry:
        delayacct_freepages_start();
        ...
        delayacct_freepages_end();
        ...
}

2.3 thrashing 耗时统计

当 task 访问刚刚到 LRU_INACTIVE 的缓存页时,被认为产生抖动。在 wait_on_page_bit_common() 函数中会统计这次抖动的耗时以及抖动的次数。

mm/filemap.c

static inline __sched int wait_on_page_bit_common(wait_queue_head_t *q,
        struct page *page, int bit_nr, int state, enum behavior behavior)
{
        ...
        if (bit_nr == PG_locked &&
            !PageUptodate(page) && PageWorkingset(page)) {
                if (!PageSwapBacked(page)) {
                        delayacct_thrashing_start();
                        delayacct = true;
                }
                psi_memstall_enter(&pflags);
                thrashing = true;
        }
        ...
        finish_wait(q, wait);

        if (thrashing) {
                if (delayacct)
                        delayacct_thrashing_end();
                psi_memstall_leave(&pflags);
        }
        ...
}

3. 初始化

在 start_kernel() 中会调用 delayacct_init() 函数对其进行初始化:

kernel/delayacct.c

void delayacct_init(void)
{
        delayacct_cache = KMEM_CACHE(task_delay_info, SLAB_PANIC|SLAB_ACCOUNT);
        delayacct_tsk_init(&init_task);
}
include/linux/delayacct.h

static inline void delayacct_tsk_init(struct task_struct *tsk)
{
        /* reinitialize in case parent's non-null pointer was dup'ed*/
        tsk->delays = NULL;
        if (delayacct_on)
                __delayacct_tsk_init(tsk);
}
kernel/delayacct.c

void __delayacct_tsk_init(struct task_struct *tsk)
{
        tsk->delays = kmem_cache_zalloc(delayacct_cache, GFP_KERNEL);
        if (tsk->delays)
                raw_spin_lock_init(&tsk->delays->lock);
}

其实,就是通过kmem_cache_zalloc() 函数从 delayacct_cache 中分配对象。

参考:

https://git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git/tree/Documentation/translations/zh_CN/accounting/delay-accounting.rst

https://justinwei.blog.csdn.net/article/details/128287053

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.mfbz.cn/a/580902.html

如若内容造成侵权/违法违规/事实不符,请联系我们进行投诉反馈qq邮箱809451989@qq.com,一经查实,立即删除!

相关文章

Hotcoin Academy 市场洞察-2024年4月15日-21日

加密货币市场表现 BTC ETF在本周出现净流出,大盘有较大跌幅,BTC一度跌破60000美金,ETH一度跌破2800美金,整体以横盘为主,行情在周末有略微回升趋势。BTC市占率创21年4月来新高,目前市值1.28万亿&#xff0c…

ElasticSearch教程入门到精通——第六部分(基于ELK技术栈elasticsearch 7.x+8.x新特性)

ElasticSearch教程入门到精通——第六部分(基于ELK技术栈elasticsearch 7.x8.x新特性) 1. Elasticsearch优化1.1 硬件选择1.1 分片策略1.1.1 分片策略——合理设置分片数1.1.2 分片策略——推迟分片分配 1.2 路由选择1.2.1 路由选择——不带routing查询1…

哪款洗地机最好用?2024年四大口碑一流品牌推荐

随着人们生活质量的提升,人们的扫地、拖地都可以用智能清洁工具来高效完成,像洗地机它集合了扫地、拖地、自清洁等功能,让我们摆脱了每次打扫卫生就像打仗一样,忙活半小时下来腰酸背痛的窘境。所以越来越多的家庭纷纷开始用洗地机…

84.柱形图中最大的矩阵

二刷终于能过了. 思路解析: 不愧是hard,第一步就很难想, 对于每一个矩阵,我们要想清楚怎么拿到最大矩阵, 对于每个height[i],我们需要找到left和right,left是i左边第一个小于height[i]的,right是右边第一个小于height[i]的,那么他的最大矩阵就是height[i] * (right-left-…

鸿蒙launcher浅析

鸿蒙launcher浅析 鸿蒙launcher源码下载鸿蒙launcher模块launcher和普通的应用ui展示的区别 鸿蒙launcher源码下载 下载地址如下: https://gitee.com/openharmony/applications_launcher 鸿蒙launcher模块 下载页面已经有相关文件结构的介绍了 使用鸿蒙编辑器D…

国外企业使用生成式人工智能实例100

每周跟踪AI热点新闻动向和震撼发展 想要探索生成式人工智能的前沿进展吗?订阅我们的简报,深入解析最新的技术突破、实际应用案例和未来的趋势。与全球数同行一同,从行业内部的深度分析和实用指南中受益。不要错过这个机会,成为AI领…

Welcome to nginx!怎么解决?

要解决 "welcome to nginx!" 错误,需要检查虚拟主机配置,启用虚拟主机,重新加载 nginx,如果无法找到虚拟主机配置文件,则创建默认页面并重新加载 nginx,这样错误消息将消失,网站将正常…

数据结构之顺顺顺——顺序表

1.浅谈数据结构 相信我们对数据结构都不陌生,我们之前学过的数组就是最基础的数据结构,它大概就长这样: 数组 而作为最简单的数据结构,数组只能帮助我们实现储存数据这一个功能,随着学习的深入,和问题的日渐…

Qt | 标准、复选、单选、工具、命令按钮大全

01、QPushButton QPushButton 类(标准按钮) 示例 3:默认按钮与自动默认按钮 02、QCheckBox QCheckBox 类(复选按钮) 1、复选按钮的第三状态(见右图 Qt5.10.1 的选中状态):是指除了选中 和未选中状态之外的第三种状态,这种状态用来指示“不变”,表 示用户既不选中也不取…

专栏目录【政安晨的机器学习笔记】

目录 政安晨的个人主页:政安晨 欢迎 👍点赞✍评论⭐收藏 收录专栏: 政安晨的机器学习笔记 希望政安晨的博客能够对您有所裨益,如有不足之处,欢迎在评论区提出指正! 本篇是作者政安晨的专栏《政安晨的机器学习笔记》的…

Python学习笔记------模块和包

Python模块 简介与作用 Python模块是一个Python文件,以.py结尾,模块能定义函数、类和变量,模块里也包含可执行的代码 模块的作用:Python中有很多各种不同的模块,每个模块都可以帮我们快速实现一些功能,我…

grafana监控模板 regex截取ip地址

查看prometheus的node服务启动指标up,也可以查看其他的服务 配置监控模板 配置正则截取ip regex截取ip地址 /.*instance"([^"]*):9100*/ #提取(instance")开头,(:9001)结束字段

北京车展“第一枪”:长安汽车发布全球首款量产可变新汽车

4月25日,万众瞩目的2024北京国际汽车展览会在中国国际展览中心如期而至。作为中国乃至全球汽车行业的盛宴,本次车展也吸引了无数业内人士的高度关注。 此次北京车展以“新时代 新汽车”为主题,汇聚了1500余家主流车企及零部件制造商&#xff…

Laravel 6 - 第十七章 配置数据库

​ 文章目录 Laravel 6 - 第一章 简介 Laravel 6 - 第二章 项目搭建 Laravel 6 - 第三章 文件夹结构 Laravel 6 - 第四章 生命周期 Laravel 6 - 第五章 控制反转和依赖注入 Laravel 6 - 第六章 服务容器 Laravel 6 - 第七章 服务提供者 Laravel 6 - 第八章 门面 Laravel 6 - …

Kettle 中将图片url转换为Base64

背景 我遇到了一个应用场景需要将订阅kafka数据中的一个字段(图片url)转换为base64 然后进行下一步操作。 实现方式 我这边的实现方式是使用javaScript去实现的 图形化逻辑如下: 这一步就是实现url转换为base64 json input的步骤&#xf…

vulnhub靶场之driftingblues-6

一.环境搭建 1.靶场描述 get flags difficulty: easy about vm: tested and exported from virtualbox. dhcp and nested vtx/amdv enabled. you can contact me by email for troubleshooting or questions. 2.靶场下载 https://www.vulnhub.com/entry/driftingblues-6,6…

【Spring AI】聊天API-OpenAI-Function Call

文章目录 Function Calling工作原理快速上手将函数注册为 Bean纯 Java 函数实现(Plain Java Functions)FunctionCallback Wrapper Specifying functions in Chat OptionsRegister/Call Functions with Prompt Options 附录:Spring AI 函数调用…

MySQL使用Sequence创建唯一主键

目录 第一章、快速了解Sequence1.1)是什么?为什么使用1.2)Sequence和自增主键的区别 第二章、在MySQL中使用Sequence2.1)创建mysql_sequence表2.1.1)创建表2.1.2)插入数据 2.2)创建函数2.2.1&am…

Kubernetes学习-核心概念篇(三) 核心概念和专业术语

🏷️个人主页:牵着猫散步的鼠鼠 🏷️系列专栏:Kubernetes渐进式学习-专栏 🏷️个人学习笔记,若有缺误,欢迎评论区指正 1. 前言 在前面两篇文章我们简单介绍了什么是K8S,以及K8S的…

Vue面试经验

Vue部分 Vue编译时声明周期的执行顺序 Vue中父子组件渲染顺序(同步引入子组件:import Son from ‘/components/son’ ) 父子组件编译时的生命周期执行顺序 这里修改data数据时也修改了dom,如过知识通过按钮对数据进行操作&…