社区编辑申请
注册/登录
SPDK动态负载均衡
服务器 数据中心
Scheduler dynamic专为节能和提高CPU利用率,尤其是在工作负载表明随着时间的推移发生大的变化的情况下,能更好地动态化管理reactor上的线程。

背景

在SPDK中,每个CPU core将对应一个reactor,创建的线程将在reactor上执行。

Figure 1 core – reactor - thread 对应关系

默认情况下,reactor以一种不断轮询的模式运行,以实现最有效的处理。但是当reactor空闲时,仍会不断轮询,这就造成了资源浪费,同时,可能有别的reactor正在运行超过自身负载的大量工作,如果将忙碌状态的reactor上的一部分线程移动到空闲的reactor上,将大大提高效率。或者此时空闲状态的reactor如果使用interrupt模式,则也可大大降低资源的损耗。由此spdk中的scheduler模块应运而生。

通常在空闲状态下,scheduler可以将reactor切换至中断模式(interrupt mode)。在 Linux 上,这是使用 epoll 实现的,但会导致 CPU 使用率降低,而且在事件发生时响应速度可能会降低。Scheduler则大大提高轻量级或大变化工作负载的效率。

Scheduler dynamic专为节能和提高CPU利用率,尤其是在工作负载表明随着时间的推移发生大的变化的情况下,能更好地动态化管理reactor上的线程。

SPDK_TOP

在介绍scheduler之前,我会先讲解一个spdk用来查看cpu使用率的工具——spdk_top。

spdk_top 应用程序类似于标准 top,它通过 SPDK 轻量级线程和轮询器提供对 CPU 内核的使用情况进行实时反馈。spdk_top 应用程序使用 RPC 命令调用来收集性能指标并将它们显示在报告中,这样您就可以分析和确定您的代码是否有效运行,以便您可以调整您的实现并从 SPDK 中获得更多。

为什么经典的top实用程序不适用于 SPDK?SPDK 采用轮询模式设计,通过分配给 SPDK 应用程序的每个 CPU 内核上运行的reactor线程来调度 SPDK 轻量级线程和轮询器。因此,标准 Linux top 实用程序对于分析 SPDK 等轮询模式应用程序的 CPU 使用率无效,因为它只会报告它们正在使用分配给它们的 CPU 资源的 100%。开发 spdk_top 实用程序是为了分析和报告用于执行实际工作与仅轮询工作的 CPU 周期。该实用程序依赖于添加到轮询器的工具来跟踪他们何时在工作与轮询工作。spdk_top 实用程序从轮询器获取细粒度指标,分析并报告每个轮询器、线程和核心的指标。

启动 spdk_top 应用程序(SPDK中有target启动时才可执行):

$SPDKDIR/build/bin/spdk_top

基本操作

  • spdk_top窗口底部的菜单显示了许多用于更改显示数据的选项。每个菜单项在方括号中都有一个与之关联的键。
  • Switch tab [1-3] - 允许选择线程/轮询器/核心选项卡。
  • Sorting [s] - 允许在排序弹出窗口中按列对显示的数据进行排序。
  • Total / Interval [t] - 将所有选项卡中的显示值更改为 Total time(自 SPDK 应用程序启动后测量)或 Interval time(自上次刷新后测量)。

选中线程后按Enter,会显示详细信息,然后可以通过按 ESC 键关闭弹出窗口:

  • help [h] – 显示更多帮助信息

Scheduler dynamic

一、Core 状态表述

  • 当前core上没有任何活动的线程时,将把对应的reactor切换为interrupt mode(直到当前core上有活跃线程时,再切换为polling mode);
  • 当线程的busy时间间隔除以当前线程的一个周期的百分比小于SCHEDULER_LOAD_LIMIT时,当前线程状态为idle;
  • 当线程的busy时间间隔除以当前线程的一个周期的百分比大于SCHEDULER_LOAD_LIMIT时,当前线程状态为busy;

二、线程调度原理

  • 当创建线程的活跃时间百分比小于SCHEDULER_LOAD_LIMIT(代码中设定为20)时,该线程为idle状态,此时该线程将移动到main core上。

Figure 2 balance 原理

示例:启动一个target

test/event/scheduler/scheduler和它的rpc plugin是测试例程,在此用来评估观测scheduler行为,实际应用中用实际需要启动的target即可。

$SPDKDIR/test/event/scheduler/scheduler -m 0xF -p 2 —wait-for-rpc &
scripts/rpc.py framework_set_scheduler dynamic
scripts/rpc.py framework_start_init

这时,启动spdk_top,可以观察到当前只有app_thread(即启动的target)一个线程,并且在我们指定的main core(core2)上。

接着创建4个idle线程(活跃时间占比分为0)

rpc_cmd —plugin scheduler_plugin scheduler_thread_create -n idle0 -m 0x1 -a 0
rpc_cmd —plugin scheduler_plugin scheduler_thread_create -n idle1 -m 0x2 -a 0
rpc_cmd —plugin scheduler_plugin scheduler_thread_create -n idle2 -m 0x4 -a 0
rpc_cmd —plugin scheduler_plugin scheduler_thread_create -n idle3 -m 0x8 -a 0

之后,我们可以观察到,虽然创建时指定了这些线程绑定不同的core,但最终仍通过scheduler将这些线程全部分配在core2(main core)上:

当main core上不存在活动线程时,该 CPU 内核的频率将随着负载的降低而降低。与其他reactor对应的所有 CPU 内核都保持在最大频率。

因此,当前的reactor并没有活跃线程,所以此时main core处于低功率状态:

2.当前线程活跃占比大于SCHEDULER_LOAD_LIMIT时,当前线程的状态为busy,scheduler将会为当前线程找一个最合适的reactor,然后将其移动过去。Main core应尽量处于空闲状态,只有当线程的执行时间超过所有线程空闲时间的总和时,main core才能包含活动线程。

  • cheduler调度的目标reactor只能在target绑定的core(即启动target时设置的cpumask对应的core)上的reactor中进行选择。
  • 调度的目标reactor必须有足够的空间能放下该线程。
  • 调度的目标reactor应是当前polling mode的reactor中最空闲的(先排除interrupt mode的reactor,除非没有合适的才会选用)。
  • 当符合以上条件时,如果 main core所对应的reactor可以容纳下当前线程,则应将当前线程移动到main core上。

示例:创建一个活跃占比为50的线程,根据调度原则此时该线程应分配在core0上:

rpc_cmd —plugin scheduler_plugin scheduler_thread_create -n busy0 -a 50

我们再创建一个活跃占比为40的线程:

rpc_cmd —plugin scheduler_plugin scheduler_thread_create -n busy1 -a 40

通过spdk_top可以看出,busy1分配在core2(main core)上。

5)当main core容纳不了该线程时,则优先选择合适的core中core id最小的core。

示例:在之前的基础上再创建一个活跃占比为40的线程:

rpc_cmd —plugin scheduler_plugin scheduler_thread_create -n busy2 -a 40

此时,core0、core1、core3都是空闲状态,core0 id最小,则优先分配在core0上。

6)当前core如果超出限制时,则之外的任一 core 都比当前core要更合适。对于超过限制的内核,将线程放在最不忙的内核上以平衡线程。

限制条件:

  • 当前core无线程或单线程
  • 没有正在运行的线程,即busy时间为0
  • 完成的工作少于限制(SCHEDULER_CORE_LIMIT 95)

示例:先清除之前所有的线程,然后在core1上创建线程busy0:

rpc_cmd —plugin scheduler_plugin scheduler_thread_create -n busy0 -m 0x2 -a 
50

再在core0上创建busy1,活跃时间占比为30:

rpc_cmd —plugin scheduler_plugin scheduler_thread_create -n busy1 -m 0x1 -a 
30

发现busy1被调度到了core1上,这是因为core0上并没有活动线程,此时应处于interrupt mode,因此core1比core0更适合去容纳busy1。

7 )如果没有找到更合适的,则不发生移动,该线程仍在当前core上。

3.调度流程图

当reactor没有调度的spdk_threads 时,它会切换到中断模式并停止主动轮询。在足够多的线程变为活动状态后,reactor将切换回轮询模式并再次为其分配线程。

如果cpu支持变频的话,则可根据需要改变main core的频率。

变频规则:

1)如果该线程不在main core上,那么为main core设置默认频率。

示例:我们先创建一个活跃占比为10 的线程,此时观察spdk_top,发现该线程被分配在main core(core2)上,此时core2的频率为1000Mhz。

之后我们再创建一个活跃占比为50的线程,将被分配在core0上,此时main core(core2)将升至默认频率2300MHz。

2)如果main core上busy时间大于idle时间,那么为main core进行升频操作。

3)其他情况则为main core进行降频操作(main core为idle,且其他core上无线程)。

示例:将除app_thread之外的其他线程都销毁掉,我们再观察spdk_top,发现main core(core2)的频率降频至1000MHz。

至此scheduler动态平衡的原理及流程规则全部讲完。

结语

Scheduler_dynamic 实现自动化动态平衡资源,是我们最终的目标,这样就可以极大程度上帮我们合理利用资源,提高工作效率的同时也可以在一定程度上延长设备寿命。同时,spdk_top也是一个非常棒的工具,可以让我们真正地看到资源的使用情况,并针对性地做出准确的分析及合理去改变设备的运行状态。目前两者都处于试验状态,并在不断地完善中。

责任编辑:未丽燕 来源: SDNLAB
相关推荐

2022-04-15 11:47:47

LVSNginx负载均衡

2022-04-21 10:01:48

VMware

2022-04-28 09:46:20

Nginx文件Linux

2022-04-21 09:26:41

FastDFS开源分布式文件系统

2010-04-22 22:36:21

F5负载均衡器

2010-05-04 13:53:15

F5负载均衡

2022-04-03 19:51:38

linux服务性能

2012-08-08 15:34:18

2010-12-17 17:46:54

负载均衡负载均衡配置

2022-04-06 06:35:58

进程命令CPU

2022-04-06 08:14:49

云原生混部系统开源

2022-04-07 08:34:46

网络设备路由器WiFi

2022-04-08 08:40:36

Nginx日志服务器

2022-04-01 15:33:22

数据中心内存存储

2022-03-29 06:40:35

虚拟化应用程序

2022-03-10 09:28:24

Kubernete云原生

2022-04-28 09:36:51

微服务性能云原生

2022-03-30 16:26:21

红帽OpenShift人工智能

2022-04-14 09:00:22

开源数据存储Ignite

2022-04-02 14:51:58

数据中心数据安全物联网

同话题下的热门内容

数据中心基础设施高可用提升研究与实践网络虚拟化和SDN在数据中心中的作用一站式全包!联想TruScale服务助力并行科技解决上云麻烦数据中心基础设施是应该纵向扩展还是横向扩展?新华三CEO于英涛:助力数字技术深入百行百业,以普惠之心弥合数字鸿沟万国数据发布2022年第一季度财报——营收同比增长31.5%,新增签约面积超18,000平方米NEC开始打造日本国内规模最大的AI研究超级计算机数据中心设计的 BIM 机会

编辑推荐

如何改变运维在数据中心中的地位详解IPv6与IPv4之间的差别!三大运营商不限量套餐哪家划算?详细对比国外12家值得注意的SD-WAN厂商UPS电源选择与电池容量计算
我收藏的内容
点赞
收藏

51CTO技术栈公众号

网站地图 真钱百家乐 捕鱼游戏 澳门赌场 申博游戏网址
申博客户端下载 申博手机下载版 澳门太阳城官方直营网 申博现金百家乐
太阳城网址 申博直营现金网 保险百家乐 盛618登入
澳门银河赌场 申博现金网 太阳城网址 菲律宾太阳城申博
申博代理 太阳城申博 捕鱼游戏 申博138官网