框架层实现cpu高负载(cpuload)的检测方案

摘要

这是2018年在小厂的老方案了,现在看方案已经过时了也不太合理,仅供参考,上层框架开启一个5分钟定时器,检测5分钟内总cpu负载和每个线程cpu负载情况,当检测到cpu负载大于绿盟性能或功耗定义的阈值时,结合场景策略,若满足非合理场景的cpu高负载异常,则根据不同等级策略进行对应cgroup控制CPU使用率、冻结和查杀等管控。

根据cpu负载值(cpu使用率)=CPU执行任务的时间与总时间的比例,故可以根据不同的获取方式有如下计算公式:

cpu负载值获取方式

计算公式

优点

缺点

adb shell top

直接可查看进程级的cpu负载百分百值

获取方便且准确度高

本身top命令会存在高cpu负载的占用

adb shell top -H

adb shell cat /proc/pid/stat

cpuload = (utime + stime / totalTime)*100%

utime数据第14位,stime数据第15位

读文件节点获取,方便代码或脚本实现

线程数量多,有时需要频繁读节点就性能很不友好

Framework 框架读文件节点/proc/pid/stat

内核层

sched.h

中task_struc接口获取utime + stime,cpuload = (utime + stime / totalTime)*100%

内存方式读取,性能效率最高,且本身cpu占用率极其低,0.3%以内

内核层到框架层通信和策略联动,虽然麻烦,从性能角度来说我觉得是最佳方案

Perfetto或trace

线程的cpu负载值 = 该线程运行总时长 / 总时长 = WallDuration / totalTime

直观准确

需要抓trace哈

adb shell dumpsys cpuinfo

直接查看进程及对应线程的cpu负载百分百值

获取方便又详细且准确率高

dump命令本身也会存在高cpu负载占用,即性能耗时

utime: 线程或进程在用户模式下花费的时间,单位是 jiffies。

stime: 线程或进程在内核模式下花费的时间,单位是 jiffies。

我认为的最佳方案是:内核层通过内存方式读取线程或进程用户态CPU时间(utime)和内核态CPU时间(stime)并换算为cpu负载值+ 框架层场景策略进行cpu高负载管控

1.cpu负载含义

因为很多人日常用语是cpu负载或cpu load,故本文cpu使用率后续都按cpu负载进行描述。

cpu使用率主要反映了CPU的忙碌程度,例如功耗待机分析中,发现灭屏下依旧有应用后台持续视频解码,带来media相关线程cpu高负载,导致cpu要一直处于工作,无法休眠,带来待机掉电快的现象。

本文的cpu负载特指cpu使用率,cpu使用率的含义:CPU在特定时间内被使用的比例,通俗的计算规则

单个线程cpu使用率 = (线程cpu运行时长 / 总时长)* 100% = (utime+stime / totalTime)* 100%

我觉得看trace文件可能更加直观描述cpu使用率:例如pid 786线程的cpu负载值 = 该线程运行总时长 / 总时长 = WallDuration / totalTime = 1552ms/9s832ms = 15%

0

上述中具体到代码中CPU负载(CPU使用率)分细为用户空间使用率(User CPU)和系统空间使用率(System CPU),分别表示在用户空间和内核空间执行的CPU时间比例。

2.cpu负载值获取方式

2.1.adb shell top

直接可查看进程级的cpu负载百分百值,优点:获取方便且准确度高,缺点:本身top命令会存在高cpu负载的占用

0

2.2.adb shell top -H

直接可查看线程级的cpu负载百分百值,优点:获取方便且准确度高,缺点:本身top命令会存在高cpu负载的占用

0

2.3.adb shell cat /proc/pid/stat

cpuload = (utime + stime / totalTime)*100%,其中utime数据第14位,stime数据第15位,优点:内存方式读取,性能效率最高,且cpu占用率及其低,缺点:线程数量多,有时需要频繁读节点就性能很不友好

0

如上获取的信息统计线程pid为1528的一些信息,其中第14位表示该线程在用户模式下的执行时间,第15位表示该进程在内核模式下的执行时间,单位为jiffies,通过这个可以获取线程的CPU使用率情况

2.3.Framework 框架读取/proc/pid/stat文件节点

cpuload = (utime + stime / totalTime)*100%,其中utime数据第14位,stime数据第15位,线程数量多,有时需要频繁读节点就性能很不友好,优点:内存方式读取,性能效率最高,且cpu占用率极其低,缺点:内核层到框架层通信和策略联动,虽然麻烦,从性能角度来说我觉得是最佳方案

    // 等同于 adb shell cat /proc/pid/stat    public long getProcessLoad(int pid) {
  
          StringBuilder targetPath = new StringBuilder();        targetPath.append(PTAH_PROC_INFO);        targetPath.append(pid);        targetPath.append(PATH_STAT);        String content = getContentWithOneLine(targetPath.toString(), String.valueOf(pid));        if (content != null) {
  
              return getPorcseeTime(content);        }        return -1;    }            private long getPorcseeTime(String content) {
  
          String[] conts = content.split(" ");        String str;        if (conts.length < 15) {
  
              return -1;        }        str = conts[13];        String strSTime = conts[14];        long utime = parseLong(str);        long stime = parseLong(strSTime);        if (utime != -1 && stime != -1) {
  
              return utime + stime;        }        return -1;    }

2.4.内核层直接内存读取cpu运行时间

android/vendor/kernel_platform/common/include/linux/sched.h,从task_struc获取utime + stime,cpuload = (utime + stime / totalTime)*100%,优点:内存方式读取,性能效率最高,且本身cpu占用率极其低,0.3%以内,缺点:

内核层到框架层通信和策略联动,虽然麻烦,从性能角度来说我觉得是最佳方案​​​​​​​

struct task_struct {
  
  	...	u64				utime;	u64				stime;	...}

2.5.Perfetto或trace换算cpu使用率

抓取trace日志方法

抓取trace日志方式1:抓atraceadb shell "atrace -o /sdcard/systrace.trace -z -b 50000 -t 60 am wm view res ss gfx view hal bionic pm sched irq freq idle disk sync binder_driver binder_lock memreclaim dalvik input"50000:缓冲区的大小,单位是消息数。30:抓取时间,单位是秒。导出traceadb pull /sdcard/systrace.trace xxx(文件存放路径)抓取trace日志方式2:perfetto命令adb shell perfetto -t 10s sched freq idle am wm gfx view binder_driver hal dalvik camera input res memory power -o /data/misc/perfetto-traces/trace_file.perfetto-trace10:抓取时间,单位是秒导出perfettoadb pull /data/misc/perfetto-traces/trace_file.perfetto-trace xxx(文件存放路径)

把Trace文件放到Perfetto UI即可,将cpu0~cpu7的区域框起来,我们就可以得到总时间和某个pid的线程运行时间。

0

例如pid 786线程的cpu负载值 = 该线程运行总时长 / 总时长 = WallDuration / totalTime = 1552ms/9s832ms = 15%

2.6.adb shell dumpsys cpuinfo

直接查看进程及对应线程的cpu负载百分百值,优点:获取方便又详细且准确率高,缺点:dump命令本身也会存在高cpu负载占用,即耗时

0

3.Framework层cpu高负载检测方案

从代码实现角度,肯定不适合直接top或dump了哈。故只需要Framework层读取节点或内核层内存读取utime + stime,然后对2次读取的时间点进行差值计算,就可以换算出对应cpu负载值了哈。

即cpuload = (utime + stime / totalTime)*100%,本文主要介绍Framework层的实现方案思路,内核层以后有缘再续.

3.1 cpu高负载检测

上层框架开启一个5分钟定时器,检测5分钟内总cpu负载和每个线程cpu负载情况,当cpu负载大于绿盟性能或功耗定义的阈值时,结合场景策略,若满足非合理场景的cpu负载占用,则根据不同等级策略进行对应cgroup控制CPU使用率、冻结和查杀等管控。

从文件节点/proc/stat读取数据,并换算系统cpu负载值(cpu使用率) = delta(userTime + nice + system)/delta(userTime + nice + system + idle + iowait + irq + softIrq) * 100%

从文件节点/proc/pid/stat读取数据,每个pid的负载值(cpu使用率)=delta(utime+stime)/delta(totalTime)* 100%

0

相关背景知识

/proc/stat 文件节点介绍 在 Linux 系统中,/proc/stat 文件提供了系统级别的统计信息,包括 CPU 使用情况。对于 CPU,这个文件提供了多个计时器,表示 CPU 在不同状态下花费的时间,单位通常是 jiffies(系统启动以来的时钟滴答数)。主要字段包括: user: 用户模式下花费的时间。 nice: 改变过优先级的用户模式下花费的时间。 system: 系统模式下花费的时间。 idle: 闲置时间。 iowait: 等待 I/O 完成的时间。 irq: 处理硬件中断的时间。 softirq: 处理软件中断的时间。 /proc/[pid]/stat 文件节点介绍 对于 Linux 系统中的每个进程,/proc 文件系统包含了一个以进程 ID 命名的目录,例如 /proc/[pid],其中包含了有关该进程的各种信息。在这个目录下,stat 文件提供了进程的状态信息,包括多个用于计算 CPU 使用率的时间度量值: utime: 该进程在用户模式下花费的时间,单位通常是 jiffies。 stime: 该进程在内核模式下花费的时间,单位同样是 jiffies。

3.2 性能管控策略

性能异常的阈值标准可以参考《软件绿色联盟应用体验标准3.0_性能标准》

绿盟性能标准文档链接:https://www.china-sga.com/spring/upload/doc/bb4ade0546b44a4c8bccb7f65a7df57a/%E8%BD%AF%E4%BB%B6%E7%BB%BF%E8%89%B2%E8%81%94%E7%9B%9F%E5%BA%94%E7%94%A8%E4%BD%93%E9%AA%8C%E6%A0%87%E5%87%863.0_%E6%80%A7%E8%83%BD%E6%A0%87%E5%87%86V1.1.pdf

0

0

3.3 功耗管控策略

功耗异常的阈值可以参考:软件绿色联盟应用体验标准6.0-功耗标准

绿盟功耗标准文档参考:https://www.china-sga.com/spring/upload/doc/e9c968ba5a284f80afaa286b6931c4cf/%E8%BD%AF%E4%BB%B6%E7%BB%BF%E8%89%B2%E8%81%94%E7%9B%9F%E5%BA%94%E7%94%A8%E4%BD%93%E9%AA%8C%E6%A0%87%E5%87%863.0_%E5%8A%9F%E8%80%97%E6%A0%87%E5%87%86V1.1.pdf

0

今天是春节前最后一天上班了,来年继续在这里搬砖。

cpu高负载检测的方案还是需要内核实现最佳,因为内存读取性能效率最高,且本身cpu负载占用率极其低可以到0.3%以内。

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

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

相关文章

Android BitmapShader简洁实现马赛克,Kotlin(一)

Android BitmapShader简洁实现马赛克&#xff0c;Kotlin&#xff08;一&#xff09; 这一篇&#xff0c; Android使用PorterDuffXfermode模式PorterDuff.Mode.SRC_OUT橡皮擦实现马赛克效果&#xff0c;Kotlin&#xff08;3&#xff09;-CSDN博客 基于PorterDuffXfermode实现马…

人工智能在数字化转型中的角色:从数据分析到智能决策

引言 在数字化转型浪潮中&#xff0c;人工智能&#xff08;AI&#xff09;正迅速崛起&#xff0c;成为推动企业创新和变革的关键力量。面对日益复杂的市场环境和激烈的行业竞争&#xff0c;企业亟需借助技术手段提高运营效率、优化决策过程&#xff0c;并增强市场竞争力。而AI…

「全网最细 + 实战源码案例」设计模式——工厂方法模式

核心思想 简单工厂模式是一种创建者模式&#xff0c;它通过一个工厂类负责创建不同类型的对象&#xff0c;根据传入的参数决定实例化的具体类&#xff0c;也被称为“静态工厂方法”模式&#xff0c;因为工厂方法通常是静态的。 结构 1. 工厂类&#xff1a; 提供一个静态方法…

我的图形布局 组织结构图布局

组织结构图布局,有的人也叫它树状布局,在图形中是经常用到的布局算法.形成类似如下图的图形布局方式 首先创建一个类, public class TreeLayouter {private int m_space 40;/// <summary>/// 空间间隔/// </summary>public int Space{get { return m_space; }se…

Golang:使用DuckDB查询Parquet文件数据

本文介绍DuckDB查询Parquet文件的典型应用场景&#xff0c;掌握DuckDB会让你的产品分析能力更强&#xff0c;相反系统运营成本相对较低。为了示例完整&#xff0c;我也提供了如何使用Python导出MongoDB数据。 Apache Parquet文件格式在存储和传输大型数据集方面变得非常流行。最…

Rust Actix Web 项目实战教程 mysql redis swagger:构建用户管理系统

Rust Actix Web 项目实战教程&#xff1a;构建用户管理系统 项目概述 本教程将指导你使用 Rust 和 Actix Web 构建一个完整的用户管理系统&#xff0c;包括数据库交互、Redis 缓存和 Swagger UI 文档。 技术栈 Rust 编程语言Actix Web 框架SQLx (MySQL 数据库)Redis 缓存Uto…

校园网上店铺的设计与实现(代码+数据库+LW)

摘 要 如今社会上各行各业&#xff0c;都喜欢用自己行业的专属软件工作&#xff0c;互联网发展到这个时候&#xff0c;人们已经发现离不开了互联网。新技术的产生&#xff0c;往往能解决一些老技术的弊端问题。因为传统校园店铺商品销售信息管理难度大&#xff0c;容错率低&a…

生成对抗网络(GAN)入门与编程实现

生成对抗网络&#xff08;Generative Adversarial Networks, 简称 GAN&#xff09;自 2014 年由 Ian Goodfellow 等人提出以来&#xff0c;迅速成为机器学习和深度学习领域的重要工具之一。GAN 以其在图像生成、风格转换、数据增强等领域的出色表现&#xff0c;吸引了广泛的研究…

26、正则表达式

目录 一. 匹配字符 .&#xff1a;匹配除换行符外的任意单个字符。 二. 位置锚点 ^&#xff1a;匹配输入字符串的开始位置。 $&#xff1a;匹配输入字符串的结束位置。 \b&#xff1a;匹配单词边界。 \B&#xff1a;匹配非单词边界。 三. 重复限定符 *&#xff1a;匹配…

电子应用设计方案101:智能家庭AI喝水杯系统设计

智能家庭 AI 喝水杯系统设计 一、引言 智能家庭 AI 喝水杯系统旨在为用户提供个性化的饮水提醒和健康管理服务&#xff0c;帮助用户养成良好的饮水习惯。 二、系统概述 1. 系统目标 - 精确监测饮水量和饮水频率。 - 根据用户的身体状况和活动量&#xff0c;智能制定饮水计划。…

数据表中的数据查询

文章目录 一、概述二、简单查询1.列出表中所有字段2.“*”符号表示所有字段3.查询指定字段数据4.DISTINCT查询 三、IN查询四、BETWEEN ADN查询1.符合范围的数据记录查询2.不符合范围的数据记录查询 五、LIKE模糊查询六、对查询结果排序七、简单分组查询1.统计数量2.统计计算平均…

【HarmonyOS NAPI 深度探索12】创建你的第一个 HarmonyOS NAPI 模块

【HarmonyOS NAPI 深度探索12】创建你的第一个 HarmonyOS NAPI 模块 在本篇文章中&#xff0c;我们将一步步走过如何创建一个简单的 HarmonyOS NAPI 模块。通过这个模块&#xff0c;你将能够更好地理解 NAPI 的工作原理&#xff0c;并在你的应用中开始使用 C 与 JavaScript 的…

步入响应式编程篇(二)之Reactor API

步入响应式编程篇&#xff08;二&#xff09;之Reactor API 前言回顾响应式编程Reactor API的使用Stream引入依赖Reactor API的使用流源头的创建 reactor api的背压模式发布者与订阅者使用的线程查看弹珠图查看形成新流的日志 前言 对于响应式编程的基于概念&#xff0c;以及J…

Unity Line Renderer Component入门

Overview Line Renderer 组件是 Unity 中用于绘制连续线段的工具。它通过在三维空间中的两个或两个以上的点的数组&#xff0c;并在每个点之间绘制一条直线。可以绘制从简单的直线到复杂的螺旋线等各种图形。 1. 连续性和独立线条 连续性&#xff1a;Line Renderer 绘制的线条…

使用Chrome和Selenium实现对Superset等私域网站的截图

最近遇到了一个问题&#xff0c;因为一些原因&#xff0c;我搭建的一个 Superset 的 Report 功能由于节假日期间不好控制邮件的发送&#xff0c;所以急需一个方案来替换掉 Superset 的 Report 功能 首先我们需要 Chrome 浏览器和 Chrome Driver&#xff0c;这是执行数据抓取的…

博客搭建 — GitHub Pages 部署

关于 GitHub Pages GitHub Pages 是一项静态站点托管服务&#xff0c;它直接从 GitHub 上的仓库获取 HTML、CSS 和 JavaScript 文件&#xff0c;通过构建过程运行文件&#xff0c;然后发布网站。 本文最终效果是搭建出一个域名为 https://<user>.github.io 的网站 创建…

C++17 新特性解析:Lambda 捕获 this

C17 引入了许多改进和新特性&#xff0c;其中之一是对 lambda 表达式的增强。在这篇文章中&#xff0c;我们将深入探讨 lambda 表达式中的一个特别有用的新特性&#xff1a;通过 *this 捕获当前对象的副本。这个特性不仅提高了代码的安全性&#xff0c;还极大地简化了某些场景下…

Python中采用.add_subplot绘制子图的方法简要举例介绍

Python中采用.add_subplot绘制子图的方法简要举例介绍 目录 Python中采用.add_subplot绘制子图的方法简要举例介绍一、Python中绘制子图的方法1.1 add_subplot函数1.2 基本语法&#xff08;1&#xff09;add_subplot的核心语法&#xff08;2&#xff09;add_subplot在中编程中的…

考研408笔记之数据结构(五)——图

数据结构&#xff08;五&#xff09;——图 1. 图的基本概念 1.1 图的定义 1.2 有向图和无向图 在有向图中&#xff0c;使用圆括号表示一条边&#xff0c;圆括号里元素位置互换没有影响。 在无向图中&#xff0c;使用尖括号表示一条边&#xff0c;尖括号里元素位置互换则表示…

研究生阶段 |《最优化方法》

文章目录 一、前言二、章节2.1 绪论2.1.1 最优化数学模型什么是最优化问题?最优化问题的数学模型最优解的一般概念最优化理论和方法?理论和方法有什么区别?最优化问题的分类具体的学习内容 2.1.2 用到的基本数学知识范数与内积方向导数、梯度、子梯度、Hesse矩阵以及Jacobi矩…