cpulimit设计理念及其思考

背景

前几天,同事咨询了我一个问题:IO占用能和cpu使用率那样,有方法来控制吗?这个问题的背景是因为客户提了两个需求,如下:

说实话,针对这两点需求,我的第一反应是有一点思路,但是并没有具体的方案。比如可以通过sleep的方式减少对CPU、IO的占用。但是如何去设计呢?令我比较有兴趣。

经讨论,进程CPU使用率可以通过开源工具cpulimit进行控制,但是进程的IO占用目前并没有好的工具可以实现。好奇心爆棚的我,比较想了解cpulimit的实现原理,以及在这之上是否能够对进程IO占用有借鉴意义。

开源工具cpulimit体积很小,就2千行代码左右,两个小时基本就能看完。了解其大致原理后,感觉对实现控制进程IO占用的功能也有一定的参考作用。通过本篇,希望能够和大家分享一下我的思路。若由任何不妥的地方或问题,欢迎评论区讨论。

cpulimit 使用及设计分析

开源工具cpulimit可通过git下载,本地编译,验证。

下载:

git clone https://github.com/opsengine/cpulimit.git

编译:

yihua@ubuntu:~/cpulimit$ make
cd src && make all
make[1]: Entering directory '/home/yihua/cpulimit/src'
cc -c list.c -Wall -g -D_GNU_SOURCE
cc -c process_iterator.c -Wall -g -D_GNU_SOURCE
cc -c process_group.c -Wall -g -D_GNU_SOURCE
cc -o cpulimit cpulimit.c list.o process_iterator.o process_group.o -Wall -g -D_GNU_SOURCE
cpulimit.c:46:18: warning: extra tokens at end of #ifdef directive#ifdef __APPLE__ || __FREEBSD__make[1]: Leaving directory '/home/yihua/cpulimit/src'
cd tests && make all
make[1]: Entering directory '/home/yihua/cpulimit/tests'
cc -o busy busy.c -lpthread -Wall -g
cc -I../src -o process_iterator_test process_iterator_test.c ../src/list.o ../src/process_iterator.o ../src/process_group.o -lpthread -Wall -g
process_iterator_test.c:31:18: warning: extra tokens at end of #ifdef directive#ifdef __APPLE__ || __FREEBSD__make[1]: Leaving directory '/home/yihua/cpulimit/tests'
yihua@ubuntu:~/cpulimit$

验证:

  1. 通过stress工具模拟CPU密集型场景。stress -c 4,4表示创建4个子进程,因为我的环境是4核,故创建4个进程。
  2. 通过mpstat查看系统的cpu使用率。mpstat -P ALL 1,显示更新频率为1s。
yihua@ubuntu:~/cpulimit$ mpstat -P ALL 1
Linux 4.15.0-213-generic (ubuntu)       12/20/2023      _x86_64_        (4 CPU)12:57:49 AM  CPU    %usr   %nice    %sys %iowait    %irq   %soft  %steal  %guest  %gnice   %idle
12:57:50 AM  all   99.25    0.00    0.75    0.00    0.00    0.00    0.00    0.00    0.00    0.00
12:57:50 AM    0  100.00    0.00    0.00    0.00    0.00    0.00    0.00    0.00    0.00    0.00
12:57:50 AM    1   97.00    0.00    3.00    0.00    0.00    0.00    0.00    0.00    0.00    0.00
12:57:50 AM    2  100.00    0.00    0.00    0.00    0.00    0.00    0.00    0.00    0.00    0.00
12:57:50 AM    3  100.00    0.00    0.00    0.00    0.00    0.00    0.00    0.00    0.00    0.0012:57:50 AM  CPU    %usr   %nice    %sys %iowait    %irq   %soft  %steal  %guest  %gnice   %idle
12:57:51 AM  all   99.50    0.00    0.50    0.00    0.00    0.00    0.00    0.00    0.00    0.00
12:57:51 AM    0  100.00    0.00    0.00    0.00    0.00    0.00    0.00    0.00    0.00    0.00
12:57:51 AM    1   98.00    0.00    2.00    0.00    0.00    0.00    0.00    0.00    0.00    0.00
12:57:51 AM    2  100.00    0.00    0.00    0.00    0.00    0.00    0.00    0.00    0.00    0.00
12:57:51 AM    3  100.00    0.00    0.00    0.00    0.00    0.00    0.00    0.00    0.00    0.0012:57:51 AM  CPU    %usr   %nice    %sys %iowait    %irq   %soft  %steal  %guest  %gnice   %idle
12:57:52 AM  all   99.00    0.00    1.00    0.00    0.00    0.00    0.00    0.00    0.00    0.00
12:57:52 AM    0   99.00    0.00    1.00    0.00    0.00    0.00    0.00    0.00    0.00    0.00
12:57:52 AM    1   97.98    0.00    2.02    0.00    0.00    0.00    0.00    0.00    0.00    0.00
12:57:52 AM    2  100.00    0.00    0.00    0.00    0.00    0.00    0.00    0.00    0.00    0.00
12:57:52 AM    3   99.00    0.00    1.00    0.00    0.00    0.00    0.00    0.00    0.00    0.00

由上可知,CPU占用率约100%。

  1. 通过cpulimit控制stress进程的cpu使用率。./src/cpulimit -p pid -l 50 -i
  2. 再观察系统的CPU使用率,如下:
yihua@ubuntu:~$ mpstat -P ALL 1
Linux 4.15.0-213-generic (ubuntu)       12/20/2023      _x86_64_        (4 CPU)01:10:45 AM  CPU    %usr   %nice    %sys %iowait    %irq   %soft  %steal  %guest  %gnice   %idle
01:10:46 AM  all   13.40    0.00    1.99    0.00    0.00    0.00    0.00    0.00    0.00   84.62
01:10:46 AM    0   11.11    0.00    2.02    0.00    0.00    0.00    0.00    0.00    0.00   86.87
01:10:46 AM    1   15.84    0.00    3.96    0.00    0.00    0.00    0.00    0.00    0.00   80.20
01:10:46 AM    2   12.87    0.00    0.99    0.00    0.00    0.00    0.00    0.00    0.00   86.14
01:10:46 AM    3   13.13    0.00    0.00    0.00    0.00    0.00    0.00    0.00    0.00   86.8701:10:46 AM  CPU    %usr   %nice    %sys %iowait    %irq   %soft  %steal  %guest  %gnice   %idle
01:10:47 AM  all   12.00    0.00    1.50    0.00    0.00    0.25    0.00    0.00    0.00   86.25
01:10:47 AM    0   10.00    0.00    2.00    0.00    0.00    0.00    0.00    0.00    0.00   88.00
01:10:47 AM    1   15.15    0.00    3.03    0.00    0.00    0.00    0.00    0.00    0.00   81.82
01:10:47 AM    2   12.00    0.00    0.00    0.00    0.00    0.00    0.00    0.00    0.00   88.00
01:10:47 AM    3   12.00    0.00    0.00    0.00    0.00    0.00    0.00    0.00    0.00   88.0001:10:47 AM  CPU    %usr   %nice    %sys %iowait    %irq   %soft  %steal  %guest  %gnice   %idle
01:10:48 AM  all   12.78    0.00    0.75    0.00    0.00    0.00    0.00    0.00    0.00   86.47
01:10:48 AM    0   15.00    0.00    3.00    0.00    0.00    0.00    0.00    0.00    0.00   82.00
01:10:48 AM    1   12.87    0.00    0.00    0.00    0.00    0.00    0.00    0.00    0.00   87.13
01:10:48 AM    2   12.12    0.00    0.00    0.00    0.00    0.00    0.00    0.00    0.00   87.88
01:10:48 AM    3   11.88    0.00    0.00    0.00    0.00    0.00    0.00    0.00    0.00   88.12

由上可知,CPU0 + CPU1 + CPU2 + CPU3约等于50。

cpulimt设计流程分析

cpulimit真的很小,建议小伙伴们自己走读一遍,加强理解。cpulimit -p pid -l 50 -i其大致流程如下:

  1. 设定一个应用时间片TIME_SLOT=100ms。计算得到 T w o r k T_{work} Twork时间和 T s l e e p T_{sleep} Tsleep时间。即 T w o r k T_{work} Twork=TIME_SLOT*limit,$T_{sleep}=TIME_SLOT*(1-limit)
  2. 通过pid,在proc文件系统中,找到进程及其子进程的信息目录。
  3. 通过获取/proc/pid/stat文件中的utimestime的时长,utime+stime得到该进程已消耗CPU的节拍数。
  4. 将进程及其子进程的节拍数相加,得到该进程消耗的总的节拍数。即为实际运行时长 T r e l w o r k T_{rel_work} Trelwork
    1. T r e l w o r k T_{rel_work} Trelwork > T w o r k T_{work} Twork,说明超过了限定值。需要释放CPU使用权。cpulimit则会想所有的进程发送信号SIGSTOP,并自身nanosleep TIME_SLOT - T r e l w o r k T_{rel_work} Trelwork时长。
    2. T r e l w o r k T_{rel_work} Trelwork < T w o r k T_{work} Twork,说明为达到限定值,可以继续占用CPU使用权。cpulimit则会想所有的进程发送信号SIGCONT,并自身nanosleep T w o r k T_{work} Twork - T r e l w o r k T_{rel_work} Trelwork 时长。
  5. 重复1~3步骤。

伪代码大致流程如下:

while(true)
{//1. 更新进程组的资源消耗update_process_group(&pgroup);...for (node = pgroup.proclist->first; node != NULL; node = node->next) {struct process *proc = (struct process*)(node->data);if (proc->cpu_usage < 0) {continue;}if (pcpu < 0) pcpu = 0;pcpu += proc->cpu_usage;}...//2. 计算sleeptime、worktimeworkingrate = MIN(workingrate / pcpu * limit, 1);tsleep.tv_nsec = TIME_SLOT * 1000 - twork.tv_nsec;//3. 唤醒进程组while (node != NULL){struct list_node *next_node = node->next;struct process *proc = (struct process*)(node->data);kill(proc->pid,SIGCONT);node = next_node;}//3.1 让进程组运行twork时长gettimeofday(&startwork, NULL);nanosleep(&twork, NULL);gettimeofday(&endwork, NULL);//3.2 让进程组sleep twork时长if (tsleep.tv_nsec>0) {node = pgroup.proclist->first;while (node != NULL){struct list_node *next_node = node->next;struct process *proc = (struct process*)(node->data);kill(proc->pid,SIGSTOP);node = next_node;}nanosleep(&tsleep,NULL);
}

思考

进程IO占用是否能够采用上述的方式:通过监控进程发送SIGSTOPSIGCONT控制目标进程的运行和休眠呢?

其实略加思考,就知道是不可行的。我们可以思考一下这个问题:客户提出IO占用可控的目的是什么?

答:无非就是防止该进程一直占用IO资源,其它业务进程获取不到资源,影响正常业务执行。如果采用cpulimit的方案,那么就会出现一种情况:若目标进程正在持有该IO资源,即使操作系统通过SIGSTOP信号,将目标进程挂起,那么其它进程也无法获取该IO资源,并不能达到客户的预期

脑洞大开(仅供参考)

通过cpulimit的设计思路,以及我们程序的应用场景,于是乎我想到了一种解决方案,似乎也能达到IO占用控制的效果。如有任何不对的地方,还请不吝指教。

我们的程序IO主要就是read/write 分区。我可以封装自己的read/write接口。其逻辑大致如下:

  1. 设定一个应用时间片TIME_SLOT=100ms。计算得到 T w o r k T_{work} Twork时间和 T s l e e p T_{sleep} Tsleep时间。即 T w o r k T_{work} Twork=TIME_SLOT*limit T s l e e p T_{sleep} Tsleep=TIME_SLOT*(1-limit)
  2. 通过proc文件系统,获取进程当前已经消耗的cpu时间 T i o 1 T_{io1} Tio1。并记录当前时间系统时间 T 总 1 T_{总1} T1
  3. 执行read/write系统调用。
  4. 通过proc文件系统,获取进程当前已经消耗的cpu时间 T i o 2 T_{io2} Tio2。并记录当前时间系统时间 T 总 2 T_{总2} T2
    1. T i o 2 T_{io2} Tio2 - T i o 1 T_{io1} Tio1 < T w o r k T_{work} Twork T 总 2 T_{总2} T2- T 总 1 T_{总1} T1 < T w o r k T_{work} Twork ,说明还未达到限定值,可以继续执行IO。
    2. T i o 2 T_{io2} Tio2 - T i o 1 T_{io1} Tio1 > T w o r k T_{work} Twork,说明单位时间内,已达到占用比,执行下一步骤休眠。
    3. T 总 2 T_{总2} T2- T 总 1 T_{总1} T1 > T w o r k T_{work} Twork,说明单位时间内,IO被其它进程抢占,未达到限定值。回到步骤2。
  5. nanosleep T w o r k T_{work} Twork - ( T 总 2 T_{总2} T2- T 总 1 T_{总1} T1) 。

以上便是我暂时的设想,当然真正实现时,需要考虑一些细节。比如步骤3和步骤4.1,若不加处理,大量的时间会消耗在proc文件系统读取上。

总结

以上便是的初步设想,后续有时间会进行代码验证,有兴趣的朋友可以关注哈。
若我的内容对您有所帮助,还请关注我的公众号。不定期分享干活,剖析案例,也可以一起讨论分享。
我的宗旨:
踩完您工作中的所有坑并分享给您,让你的工作无bug,人生尽是坦途。
在这里插入图片描述

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

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

PIC单片机项目(5)——基于PIC16F877A的多功能防盗门

1.功能设计 本次设计的功能如下&#xff1a;如果红外对管检测到有人经过&#xff0c;LCD1602可以显示&#xff0c;我设计的是显示字符串“someone”。 如果有人强行破门&#xff0c;FSR402压力传感器会检测到压力过大&#xff0c;然后触发蜂鸣器报警&#xff0c;LCD1602也显示“…

物奇平台消息发收功能实现

物奇平台消息发收功能实现 是否需要申请加入数字音频系统研究开发交流答疑群(课题组)?可加我微信hezkz17, 本群提供音频技术答疑服务,+群赠送语音信号处理降噪算法,蓝牙耳机音频,DSP音频项目核心开发资料, 1 外设中断消息发送方法

实验4.2 默认路由和浮动静态路由的配置

实验4.2 默认路由和浮动静态路由的配置 一、任务描述二、任务分析三、具体要求四、实验拓扑五、任务实施1.路由器的基本配置。2.配置默认路由&#xff0c;实现全网互通。3.配置浮动静态路由&#xff0c;实现链路备份。 六、任务验收七、任务小结八、知识链接1&#xff0e;默认路…

2023 英特尔On技术创新大会直播 |AI小模型更有性价比

前言&#xff1a; 今年是引爆AI的一年&#xff0c;从幼儿园的小朋友到80岁的老奶奶都认识AI&#xff0c;享受AI带来的便捷&#xff0c;都在向市场要智能&#xff0c;但AI的快速发展离不开底层硬件设施的革新。 英特尔是全球知名的半导体公司&#xff0c;专注于计算机处理器和芯…

Goby 漏洞发布| Apusic 应用服务器 createDataSource 远程代码执行漏洞

漏洞名称&#xff1a;Apusic 应用服务器 createDataSource 远程代码执行漏洞 English Name&#xff1a;Apusic Application Server loadTree Remote Code Execution Vulnerability CVSS core: 9.8 影响资产数&#xff1a; 31410 漏洞描述&#xff1a; 金蝶 Apusic 应用服务…

第三节TypeScript 基础类型

1、typescript的基础类型 如下表&#xff1a; 数据类型 关键字 描述 任意类型 any 生命any的变量可以赋值任意类型的值 数字类型 number 整数或分数 字符串类型 string 使用单引号&#xff08;‘’&#xff09;或者双引号&#xff08;“”&#xff09;来表示字符串…

企业数字化转型如何影响企业 ESG 表现 —来自中国上市公司的证据(数据复现+代码)

数据来源&#xff1a;自主整理 时间跨度&#xff1a;2010-2020年 数据范围&#xff1a;中国沪深 A 股上市公司 数据指标&#xff1a; 类型 变量 符号 变量定义 证券代码 stkcd 年份 year 股票简称 name 被解释变量 ESG ESG 华证ESG季度评级赋值1-9分&#xff0c;取…

xxl-job 分布式调度学习笔记

1.概述 1.1什么是任务调度 业务场景&#xff1a; 上午10点&#xff0c;下午2点发放一批优惠券 银行系统需要在信用卡到期还款日的前三天进行短信提醒 财务系统需要在每天凌晨0:10分结算前一天的财务数据&#xff0c;统计汇总 不同系统间的数据需要保持一致&#xff0c;这时…

flask 之上传与下载

from flask import Flask, render_template, request, send_from_directory, redirect, url_for import osapp Flask(__name__)# 上传文件存储路径 UPLOAD_FOLDER uploads app.config[UPLOAD_FOLDER] UPLOAD_FOLDERapp.route(/) def index():# 确保上传文件夹存在if not os.…

牛客BC115 超级圣诞树

万众瞩目 在上一篇我们介绍了一个圣诞树的打印&#xff0c;而这道题与上次不同的是他的基本单位是一直在变的 我建议先把上一个搞懂在写这道题这个。 牛客网BC114 圣诞树-CSDN博客 ok那么正文开始 题目如下 今天是圣诞节&#xff0c;牛牛要打印一个漂亮的圣诞树送给想象中…

Unity 通过代码将一张大图切成多个小图的方法

在Unity 中要通过代码将一张贴图切割成多张小图&#xff0c;可以使用以下方法&#xff1a; /// <summary>/// 把一张图片切割成多张使用/// </summary>/// <param name"texture">原图</param>/// <param name"rows">切割的行…

[DNS网络] 网页无法打开、显示不全、加载卡顿缓慢 | 解决方案

[网络故障] 网页无法打开、显示不全、加载卡顿缓慢 | 解决方案 问题描述 最近&#xff0c;我在使用CSDN插件浏览 MOOC 网站时&#xff0c;遇到了一些网络故障。具体表现为&#xff1a; MOOC 中国大学慕课网&#xff1a;www.icourse163.org点击CSDN插件首页的 MOOC&#xff08…

VSCode调试Vue项目

前言 代码在某个平台运行时&#xff0c;会将运行时的状态通过某种方式暴露出来。这些状态信息可以通过某种方式传递给开发工具&#xff0c;以便进行UI的展示和交互。这样的交互可以辅助开发者排查问题、梳理流程&#xff0c;并更好地了解代码的运行状态。这就是我们通常所说的调…

Excel如何将行的值转换为列值?

问题:Excel如何将行的值转换为列值?(如图左表变成右表) 1.用 SUMIFS(求和区域, 条件区域1, 条件1, [条件区域2, 条件2], ...)函数 比如:=SUMIFS($C$2:$C$8,$A$2:$A$8,H3,$B$2:$B$8,"快车") 2.直接用简单的透视表 (1)随机点击目标目标表格任何位置,点击插入…

C语言—每日选择题—Day56

指针相关博客 打响指针的第一枪&#xff1a;指针家族-CSDN博客 深入理解&#xff1a;指针变量的解引用 与 加法运算-CSDN博客 第一题 1. 以下叙述中正确的是&#xff08;&#xff09; A&#xff1a;\0 表示字符 0 B&#xff1a;"a" 表示一个字符常量 C&#xff1a;表…

(企业 / 公司项目)Java如何打印漂亮的日志?

启动类 首先在idea创建一个项目这里就不演示了&#xff0c;直接看demo 找到项目的启动类&#xff0c;首先把启动类日志打印基本信息&#xff0c;这样就不用找来找去找不到地址以及端口 主要作用就是启动一个Spring Boot应用程序&#xff0c;并获取程序的运行环境。首先创建一…

javaSE学习-4-类和对象

1. 面向对象的初步认知 1.1 什么是面向对象 面向对象编程&#xff08;OOP&#xff09;是一种程序设计范式&#xff0c;它将程序中的数据和操作数据的方法封装到对象中。在面向对象的世界里&#xff0c;一切都被视为对象&#xff0c;这些对象可以拥有数据&#xff08;成员变量&…

大数据机器学习:从理论到实战,探索学习率的调整策略

大数据机器学习&#xff1a;从理论到实战&#xff0c;探索学习率的调整策略 全文目录 大数据机器学习&#xff1a;从理论到实战&#xff0c;探索学习率的调整策略一、引言二、学习率基础定义与解释学习率与梯度下降学习率对模型性能的影响 三、学习率调整策略常量学习率时间衰减…

《PySpark大数据分析实战》-16.云服务模式Databricks介绍运行案例

&#x1f4cb; 博主简介 &#x1f496; 作者简介&#xff1a;大家好&#xff0c;我是wux_labs。&#x1f61c; 热衷于各种主流技术&#xff0c;热爱数据科学、机器学习、云计算、人工智能。 通过了TiDB数据库专员&#xff08;PCTA&#xff09;、TiDB数据库专家&#xff08;PCTP…

【大数据面试】Flink面试题附答案

目录 ✅Flink介绍、特点、应用场景 ✅Flink与Spark Streaming的区别 ✅Flink有哪些部署模式 ✅Flink架构 ✅怎么设置并行度&#xff1f; ✅什么是算子链&#xff1f; ✅什么是任务槽&#xff08;Task Slots&#xff09;&#xff1f; ✅任务槽和并行度的关系 ✅Flink作…