浅谈下Load_balance函数情景分析~(上文)

前言

本文出现的内核代码来自Linux5.10.61,为了减少篇幅,我们对引用的代码进行了删减如果有兴趣,读者可以配合完整的源代码代码阅读本文。

一、概述

本文主要分成三个部分,第一个部分就是本章,简单的描述了本文的结构和阅读前提条件。第二章是对load_balance函数设计的数据结构进行描述。这一章不需要阅读,只是在有需要的时候可以查阅几个主要数据结构的各个成员的具体功能。随后的若干个章节是以load_balance函数为主线,对各个逻辑过程进行逐行分析。

需要强调的是本文不是独立成文的,很多负载均衡的基础知识(例如sched domain、sched group,什么是负载、运行负载、利用率utility,什么是均衡......)在CFS任务负载均衡系列文章的第一篇已经描述,如果没有阅读过,强烈建议提前阅读。如果已经具体负载均衡的基础概念,那么希望本文能够给你带来研读代码的快乐。

二、load_balance函数使用的数据结构

1、structlb_env在负载均衡的时候,通过lb_env数据结构来表示本次负载均衡的上下文:


浅谈下Load_balance函数情景分析~(上文)

2、structsd_lb_stats在负载均衡的时候,通过sd_lb_stats数据结构来表示scheddomain的负载统计信息:


浅谈下Load_balance函数情景分析~(上文)

3、structsg_lb_stats在负载均衡的时候,通过sg_lb_stats数据结构来表示schedgroup的负载统计信息:


浅谈下Load_balance函数情景分析~(上文)

4、structsched_group_capacity数据结构sched_group_capacity用来描述schedgroup的算力信息:


浅谈下Load_balance函数情景分析~(上文)


更多linux内核视频教程文档资料免费领取后台私信【内核】自行获取.

浅谈下Load_balance函数情景分析~(上文)

浅谈下Load_balance函数情景分析~(上文)

Linux内核源码/内存调优/文件系统/进程管理/设备驱动/网络协议栈-学习视频教程-腾讯课堂


三、load_balance函数整体逻辑

从本章开始我们进行代码分析,这一章是load_balance函数的整体逻辑,后面的章节都是对本章中的一些细节内容进行补充。load_balance函数实在是太长了,我们分段解读。第一段的逻辑如下:


浅谈下Load_balance函数情景分析~(上文)

A、对load_balance函数的参数以及返回值解释如下:


浅谈下Load_balance函数情景分析~(上文)

A、初始化本次负载均衡的上下文信息。具体可以参考对struct lb_env的解释。初始化完第一轮均衡的上下文,下面就看看具体的均衡操作为何。第二段的逻辑如下:

浅谈下Load_balance函数情景分析~(上文)

A、确定本轮负载均衡涉及的cpu,因为是第一轮均衡,所以所有的sched domain中的cpu都参与均衡(cpu_active_mask用来剔除无法参与均衡的CPU)。后续如果发现一些异常状况(例如由于affinity原因无法完成任务迁移),那么会清除选定的busiest cpu,跳转到redo进行全新一轮的均衡。

B、判断env->dst_cpu这个CPU是否适合做指定scheddomain的均衡。如果被认定不适合发起balance,那么后续更高层level的均衡也不必进行了(设置continue_balancing等于0)。在base domain,每个group都只有一个CPU,因此所有的cpu都可以发起均衡。在non-base domain,每个group有多个CPU,如果每一个cpu都可以进行均衡,那么均衡就太密集了,白白消耗CPU资源,所以限制只有第一个idle的cpu可以发起均衡,如果没有idle的CPU,那么group中的第一个CPU可以发起均衡。

C、在该sched domain中寻找最繁忙的schedgroup。具体逻辑后文会详细描述。如果没有找到busiest group,那么退出本level的均衡

D、在最繁忙的sched group寻找最繁忙的CPU。具体逻辑后文会详细描述。如果没有找到busiest cpu,那么退出本level的均衡至此已经找到了source CPU,dest cpu就是发起均衡的thiscpu,那么就可以开始第一轮的任务迁移了,具体的代码逻辑如下:


浅谈下Load_balance函数情景分析~(上文)

A、如果要从busiest cpu迁移任务到this cpu,那么至少要有可以拉取的任务。在拉取任务之前,我们先设定all pinned标志。当然后续如果发现不是all pinned的状况就会清除这个标志。

B、为了达到sched domain的负载均衡,我们需要进行任务的迁移,因此我们这里需要遍历busiest rq上的任务,看看哪些任务最适合被迁移到this cpu rq。

loop_max就是扫描src rq上runnable任务的次数。一般而言,任务迁移上限就是busiest runqueue上的任务个数,确保了每一个任务都被扫描到,但是一次均衡操作不适合迁移太多的任务(关中断区间太长),因此,即便busiest runqueue上的任务个数非常多,一次任务迁移不能大于sysctl_sched_nr_migrate个(目前设定是32个)。

C、和redo不同,跳转到more_balance的新一轮迁移不需要寻找busiestcpu,只是继续扫描busiest rq上的任务列表,寻找适合迁移的任务。

D、detach_tasks函数用来从busiestcpu的rq中摘取适合的任务。具体逻辑后面会详细描述。由于关中断时长的问题,detach_tasks函数也不会一次性把所有任务迁移到dest cpu上。

E、将detach_tasks函数摘下的任务挂入到srcrq上去。由于detach_tasks、attach_tasks会进行多轮,ld_moved记录了总共迁移的任务数量,cur_ld_moved是本轮迁移的任务数

F、在任务迁移过程中,src cpu的中断是关闭的,为了降低这个关中断时间,迁移大量任务的时候需要break一下。至此已经对dest rq上的任务列表完成了loop_max次扫描,要看情况是否要发起下一轮次的均衡。具体代码如下:


浅谈下Load_balance函数情景分析~(上文)

A、如果sched domain仍然未达均衡均衡状态,并且在之前的均衡过程中,有因为affinity的原因导致任务无法迁移到dest cpu,这时候要继续在src rq上搜索任务,迁移到备选的dest cpu,因此,这里再次发起均衡操作。这里的均衡上下文的dest cpu设定为备选的cpu,loop也被清零,重新开始扫描。

B、本层次的sched domain因为affinity而无法达到均衡状态,我们需要把这个状态标记到上层sched domain的group中去,在上层sched domain进行均衡的时候,该group会被判定为group_imbalanced,从而有更大的机会选定为busiest group,从而解决该sched domain的均衡问题。

C、如果选中的busiest cpu上的任务全部都是通过affinity锁定在了该cpu上,那么清除该cpu(为了确保下轮均衡不考虑该cpu),再次发起均衡。这种情况下,需要重新搜索source cpu,因此跳转到redo。

至此,source rq上的cfs任务链表已经被遍历(也可能遍历多次),基本上对runnable任务的扫描已经到位了,如果不行就只能考虑running task了,具体代码逻辑如下:


浅谈下Load_balance函数情景分析~(上文)

A、经过上面的一系列操作,没有完成任何任务的迁移,那么就需要累计sched domain的均衡失败次数。这个失败次数会导致后续进行更激进的均衡,例如迁移cache hot的任务、启动active balance。此外,这里过滤掉了new idle balance的失败,仅统计周期性均衡失败的次数,这是因为系统中new idle balance次数太多,累计其失败次数会导致nr_balance_failed过大,容易触发后续激进的均衡。

B、判断是否要启动active balance。所谓activebalance就是把当前正在运行的任务迁移到dest cpu上。也就是说经过前面一番折腾,runnable的任务都无法迁移到dest cpu,从而达到均衡,那么就考虑当前正在运行的任务。

C、在启动active balance之前,先看看busiestcpu上当前正在运行的任务是否可以运行在dest cpu上。如果不可以的话,那么不再试图执行均衡操作,跳转到out_one_pinned

D、Busiest cpurunqueue上设置active balance的标记

E、发起主动迁移F、完成了至少一个任务迁移,重置均衡失败计数Load_balance最后一段的程序逻辑主要是进行一些清理工作和设定balance_interval的工作,逻辑比较简单,不再详述,我们会在随后的章节中对load_balance函数中的一些过程做进一步的描述。

四、寻找sched domain中最繁忙的group

判断当前scheddomain是否均衡并返回最忙group的功能是在find_busiest_group函数中完成的,我们分段来描述该函数的逻辑,我们先看第一段代码:


浅谈下Load_balance函数情景分析~(上文)

A、负载信息都是不断的在变化,在寻找最繁忙group的时候,我们首先要更新scheddomain负载均衡信息,以便可以根据最新的负载情况来搜寻。update_sd_lb_stats会更新该sched domain上各个sched group的负载和算力,得到local group以及非local group最忙的那个group的均衡信息,以便后续给出最适合的均衡决策。具体的逻辑后面的章节会详述

B、在系统没有进入overutilized状态之前,EAS起作用。如果EAS起作用,那么负载可能是不均衡的(考虑功耗),因此,这时候不进行负载均衡,依赖task placement的结果。update_sd_lb_stats函数找到了busiestgroup,结合local group的状态就可以判断系统的不均衡状态了。当然有一些比较容易判断的场景,具体代码如下:


浅谈下Load_balance函数情景分析~(上文)

A、如果没有找到最忙的那个group,说明当前scheddomain中,其他的非local的最繁忙的group(后文称之busiest group)没有可以拉取到local group的任务,不需要均衡处理。B、Busiestgroup中有misfit task,那么必须要进行均衡,把misfit task拉取到local group中C、Busiestgroup是一个由于cpu affinity导致的不均衡,这个不均衡在底层sched domain无法处理。D、如果local group比busiestgroup还要忙,那么不需要进行均衡(目前的均衡只能从其他group拉任务到local group)其他的复杂场景需要进一步比拼local group和busiest group的情况,group_overloaded状态下判断是否均衡的代码如下:


浅谈下Load_balance函数情景分析~(上文)

A、如果local group处于overloaded状态,那么需要通过avg_load的比拼来做均衡决策B、如果local group的平均负载比busiestgroup还要高,那么不需要进行均衡C、如果local group的平均负载高于scheddomain的平均负载,那么不需要进行均衡D、虽然busiest group的平均负载高于localgroup,但是高的不多,那也不需要进行均衡,毕竟均衡需要额外的开销。具体的门限是有sched domain的imbalance_pct确定的。非group_overloaded不看平均负载,主要看idlecpu的情况,具体代码如下:


浅谈下Load_balance函数情景分析~(上文)

A、这里处理busiest group没有overload的场景,这时候说明该scheddomain中其他的group的算力都是cover当前的任务负载,是否要进行均衡,主要看idle cpu的情况B、反正busiest group当前算力能处理其runqueue上的任务,那么在本CPU繁忙的情况下没有必要进行均衡,因为这时候关注的是idle cpu,即让更多的idle cpu参与运算,因此,如果本CPU不是idle cpu,那么判断sched domain处于均衡状态。C、如果busiest group中有更多的idle CPU,那么也没有必要进行均衡D、如果busiest group中只有一个cfs任务,那么也没有必要进行均衡E、所有其他情况都是需要进行均衡。calculate_imbalance用来计算scheddomain中不均衡的状态是怎样的。具体如何进行均衡决策可以参考下面的表格:


浅谈下Load_balance函数情景分析~(上文)


浅谈下Load_balance函数情景分析~(上文)

Balanced:该scheddomain处于均衡状态,不需要均衡。Force:该scheddomain处于不均衡状态,通过calculate_imbalance计算不均衡指数,并有可能通过任务迁移让系统进入均衡状态。Avg load:通过schedgroup的平均负载来判断是否需要均衡。尽量不均衡,除非非常的不均衡(通过sched domain的imbalance_pct参数来设定)Nr idle:dest cpu处于idle状态,并且localgroup的idle cpu个数大于busiest group的idle cpu个数,只有在这种情况下才进行均衡。

由于文章篇幅有限,下文继续讲解

浅谈下Load_balance函数情景分析~(上文)

发表评论
留言与评论(共有 0 条评论) “”
   
验证码:

相关文章

推荐文章