|
|
CPU负载监视器每秒读一次 /proc/stat采样
- /**
- * 案例43:CPU负载监视器每秒读一次 /proc/stat采样
- *
- * 主要功能:每秒读一次 /proc/stat,用前后两次采样的差值算出整机 CPU 使用率,
- * 实时滚动 20 格负载条(█░),超过警戒线立刻 ⚠ 提示;跑完出峰值/谷值/均值/
- * 超载轮数统计卡,成绩写 CSV 台账并 stat 复查字节数。
- *
- * 实际作用:
- * 1. 跑重活(打包/备份/批量拉起)前后各测一遍,看谁在吃 CPU、机器扛不扛得住;
- * 2. 判断云手机宿主机有没有超售——别人卡顿时你的负载条也跟着爆表就是证据;
- * 3. 给录像攒素材:负载条一秒一格滚动,峰谷揭晓自带节奏。
- *
- * 用法:直接运行,约 25 秒收工。配置:采样轮数/采样间隔毫秒/警戒线(百分比)。
- * 写法:Rhino ES5,全 var,函数先定义后调用,main() 末尾启动;等待只用 sleep.millisecond。
- */
- // ========== 配置区 ==========
- var 采样轮数 = 15;
- var 采样间隔毫秒 = 1000;
- var 警戒线 = 70;
- var 落盘目录 = "/sdcard/auto";
- var 台账文件 = 落盘目录 + "/CPU负载_台账.csv";
- // ========== 一、通道封装 ==========
- function adb跑(命令) {
- try {
- var 数据 = JSON.parse(adb.exec(命令, false));
- var 成 = 数据.success == null ? "" : ("" + 数据.success);
- var 错 = 数据.errorMsg == null ? "" : ("" + 数据.errorMsg).trim();
- return { 成: 成, 错: 错 };
- } catch (e) {
- return { 成: "", 错: "exec异常 " + e };
- }
- }
- function 补零(n) { return n < 10 ? "0" + n : "" + n; }
- function 当前时刻() {
- var d = new Date();
- return 补零(d.getHours()) + ":" + 补零(d.getMinutes()) + ":" + 补零(d.getSeconds());
- }
- function 记台账(行) {
- adb跑("mkdir -p " + 落盘目录);
- adb跑("echo " + 行 + " >> " + 台账文件);
- }
- // ========== 二、节奏输出 ==========
- function 节奏倒计时(秒数, 干什么) {
- for (var i = 秒数; i > 0; i--) {
- printl("⏰ " + i + " 秒后:" + 干什么);
- sleep.millisecond(1000);
- }
- printl("🎬 " + 干什么 + " —— 开始");
- sleep.millisecond(400);
- }
- // ========== 三、CPU 采样 ==========
- // 读 /proc/stat 首行,拆成 {忙, 闲, 总};读不到返回 null
- function 读CPU快照() {
- var r = adb跑("cat /proc/stat");
- var m = r.成.match(/cpu\s+(\d+)\s+(\d+)\s+(\d+)\s+(\d+)\s+(\d+)\s+(\d+)\s+(\d+)/);
- if (m == null) return null;
- var user = parseInt(m[1], 10);
- var nice = parseInt(m[2], 10);
- var system = parseInt(m[3], 10);
- var idle = parseInt(m[4], 10);
- var iowait = parseInt(m[5], 10);
- var irq = parseInt(m[6], 10);
- var softirq = parseInt(m[7], 10);
- var 忙 = user + nice + system + irq + softirq;
- var 闲 = idle + iowait;
- return { 忙: 忙, 闲: 闲, 总: 忙 + 闲 };
- }
- // 两次快照差值算使用率,保留 1 位小数
- function 算使用率(上, 今) {
- var 总差 = 今.总 - 上.总;
- if (总差 <= 0) return 0;
- var 忙差 = 今.忙 - 上.忙;
- return Math.round(忙差 / 总差 * 1000) / 10;
- }
- // 20 格负载条
- function 负载条(百分比) {
- var 满格 = Math.round(百分比 / 5);
- if (满格 > 20) 满格 = 20;
- if (满格 < 0) 满格 = 0;
- var 条 = "";
- for (var i = 0; i < 20; i++) {
- 条 = 条 + (i < 满格 ? "█" : "░");
- }
- return 条;
- }
- function 状态标签(百分比) {
- if (百分比 >= 警戒线) return "⚠超载";
- if (百分比 >= 40) return "偏忙";
- return "正常";
- }
- // 百分比统一带 1 位小数显示
- function 补零一(n) {
- var s = "" + n;
- if (s.indexOf(".") < 0) s = s + ".0";
- return s;
- }
- // ========== 主流程 ==========
- function main() {
- printl("=== 案例43 CPU负载监视器 启动:采样 " + 采样轮数 + " 轮,间隔 " + 采样间隔毫秒 + " 毫秒,警戒线 " + 警戒线 + "% ===");
- sleep.millisecond(500);
- 节奏倒计时(3, "读取CPU基线(/proc/stat)");
- var 上 = 读CPU快照();
- if (上 == null) {
- printl("❌ /proc/stat 读不到,这台机没有 procfs 通道,收工");
- return;
- }
- printl("📸 基线已取得,开始逐秒采样");
- printl("");
- 记台账("时刻,轮次,CPU百分比,状态");
- var 峰 = 0;
- var 峰轮 = 0;
- var 谷 = 101;
- var 谷轮 = 0;
- var 合计 = 0;
- var 超载数 = 0;
- var 实采轮数 = 0;
- for (var 轮 = 1; 轮 <= 采样轮数; 轮++) {
- sleep.millisecond(采样间隔毫秒);
- var 今 = 读CPU快照();
- if (今 == null) {
- printl("❌ 第 " + 轮 + " 轮采样读取失败,提前收工");
- break;
- }
- var 率 = 算使用率(上, 今);
- 上 = 今;
- var 标签 = 状态标签(率);
- printl("第 " + 补零(轮) + "/" + 采样轮数 + " 轮 " + 补零一(率) + "% " + 负载条(率) + " [" + 标签 + "]");
- 记台账(当前时刻() + "," + 轮 + "," + 率 + "," + 标签);
- if (率 > 峰) { 峰 = 率; 峰轮 = 轮; }
- if (率 < 谷) { 谷 = 率; 谷轮 = 轮; }
- if (率 >= 警戒线) 超载数++;
- 合计 = 合计 + 率;
- 实采轮数++;
- }
- if (实采轮数 === 0) {
- printl("❌ 一轮都没采到,收工");
- return;
- }
- var 均值 = Math.round(合计 / 实采轮数 * 10) / 10;
- printl("");
- printl("========== 📊 负载统计卡 ==========");
- printl(" 📈 峰值 : " + 补零一(峰) + "%(第 " + 峰轮 + " 轮)");
- printl(" 📉 谷值 : " + 补零一(谷 >= 101 ? 0 : 谷) + "%(第 " + 谷轮 + " 轮)");
- printl(" 📊 均值 : " + 补零一(均值) + "%");
- printl(" ⚠ 超载 : " + 超载数 + " / " + 采样轮数 + " 轮(警戒线 " + 警戒线 + "%)");
- if (超载数 === 0) {
- printl(" ✅ 全程没碰警戒线,机器扛得住");
- } else {
- printl(" 🔥 有 " + 超载数 + " 轮超载,跑重活前先给它减减负");
- }
- 记台账(当前时刻() + ",统计," + 均值 + ",峰" + 峰 + "/谷" + 谷 + "/超载" + 超载数);
- var 查 = adb跑("stat -c %s " + 台账文件);
- if (查.成 !== "") {
- printl("📒 台账已落盘: " + 台账文件 + "(" + 查.成.trim() + " 字节)");
- } else {
- printl("⚠ 台账复查失败: " + 查.错);
- }
- printl("=== 案例43 收工 ===");
- }
- main();
复制代码
|
|