目录

openKylin 启动性能分析与优化

项目优化方案完整思路与实现解析

1. 项目要解决的问题

本项目不是单纯追求 systemd-analyze 输出中的某一个启动数字,而是针对桌面 Linux 用户真正感知到的两段启动过程进行分析和优化:

  1. 从内核开始执行,到图形登录界面可以显示和响应;
  2. 从用户会话启动,到桌面、任务栏、文件能力、输入法等核心组件全部可用。

优化必须同时满足以下要求:

  • 能解释时间消耗发生在哪条依赖链上;
  • 不通过关闭图形登录、网络、DNS 或桌面核心能力换取分数;
  • 不把必要初始化简单延后,造成登录后首次使用明显卡顿;
  • 可以在优化前预览计划,在异常时恢复;
  • 能在 openKylin 之外的 systemd 桌面发行版上安全迁移;
  • 测量、优化、复测、对比和出图均可重复执行并保留原始证据。

项目最终形成以下闭环:

flowchart LR
    A["采集 baseline"] --> B["分析 blame 与 critical-chain"]
    B --> C["识别关键路径、后台争用和无效服务"]
    C --> D["dry-run 检查优化计划"]
    D --> E["应用白名单优化"]
    E --> F["重启并采集 optimized"]
    F --> G["健康检查与量化对比"]
    G --> H["多轮中位数、汇总和出图"]
    G -->|"功能异常"| I["按 manifest 还原"]

核心脚本对应关系如下:

脚本 职责 是否修改系统
scripts/measure-boot.sh 采集启动时间、关键路径、启动图和桌面健康状态 否,只读
scripts/auto-optimize.sh 根据白名单和硬件探测生成并应用优化计划 是,需要 root
scripts/compare-boot.sh 对比两次测量结果并计算绝对变化和百分比 否,只读
scripts/generate-test-assets.py 汇总多轮数据,计算中位数并生成核心分析图 否,只处理仓库数据
scripts/generate-result-cards.py 为每轮测试和每个环境生成可视化结果卡片 否,只处理仓库数据

2. 统一计时模型

项目统一使用内核 monotonic clock 的 0 点作为 t0,即内核开始执行的时刻。BIOS、UEFI、固件和 GRUB 菜单等待不计入结果。

阶段 定义 实现方式
Kernel t0 到 systemd PID 1 启动 解析 systemd-analyze 的 kernel 时间
Userspace systemd 接管后到用户空间启动完成 解析 systemd-analyze 的 userspace 时间
登录就绪 t0graphical.target 或 greeter 实际显示 systemd 结果与 journal monotonic 日志结合
会话启动 t0 到 UKUI/GNOME 用户会话出现 从本次启动 journal 中查找会话标记
桌面可用 t0 到桌面核心组件全部出现 取各桌面组件首次出现时间的最大值
登录到桌面 会话启动到桌面核心组件就绪 desktop ready - session start

这样可以区分三个经常被混淆的概念:

  • graphical.target 到达不一定代表 greeter 已经真实显示;
  • greeter 已显示不代表用户登录后的桌面已经可用;
  • systemd 总启动变快不一定代表桌面体验同步改善。

measure-boot.sh 因此同时保存 systemd 指标和 journal 中的实际桌面事件,避免只依赖单一口径。

3. 优化前的瓶颈分析

项目先使用以下证据定位问题,再决定是否优化某个单元:

systemd-analyze
systemd-analyze blame
systemd-analyze critical-chain
systemd-analyze critical-chain graphical.target
systemd-analyze plot
systemctl list-unit-files --state=enabled

分析得到的主要问题分为四类。

3.1 冗余服务进入图形启动关键路径

openKylin 基线环境的关键链中,dnsmasq.service 被挂在 multi-user.target 之前,并要求网络目标就绪:

graphical.target └─multi-user.target └─dnsmasq.service └─network.target └─NetworkManager.service └─dbus.service

该测试环境实际使用 systemd-resolved 提供 DNS 解析,/etc/resolv.conf 并不指向 dnsmasq。因此 dnsmasq 对该客户端 VM 是冗余的,却把 NetworkManager 拉起过程带入 graphical.target 关键路径。

对应优化不是让网络更晚可用,而是移除一个不参与实际 DNS 解析的冗余依赖,使网络初始化与图形登录可以并行推进。这属于“无效等待消除 + 关键路径解耦”。

auto-optimize.sh 不会自动证明每台机器的 DNS 拓扑。应用前必须通过 readlink -f /etc/resolv.confresolvectl status 等命令人工确认 dnsmasq 不是实际解析器。如果机器依赖本地 dnsmasq 提供 DNS、DHCP 或虚拟网络能力,不得裁剪该服务。

3.2 等待网络完全在线阻塞桌面登录

部分基线轮次中还存在以下链路:

graphical.target └─network-online.target └─NetworkManager-wait-online.service └─NetworkManager.service

普通桌面登录通常只要求 NetworkManager 正常启动,不需要等待所有网络接口完成联网。NetworkManager-wait-online.service 在无线网络不可用、DHCP 较慢或虚拟网卡状态不稳定时可能产生较长等待,因此安全档会在确认桌面不依赖 network-online.target 后裁剪该等待单元。

3.3 后台维护任务与桌面加载竞争资源

apt-daily*kylin-source-update*motd-newsdpkg-db-backupe2scrub_all 等 timer 不一定处在 graphical.target 的直接关键路径上,但可能在开机后集中触发,与 UKUI/GNOME 桌面组件竞争磁盘 I/O 和 CPU。

这类任务主要影响“用户会话启动到桌面可用”阶段。优化方式是 mask 对应 timer,使其不在启动后自动触发。软件更新和维护能力本身没有被删除,但自动定时触发会保持关闭,直到执行还原;需要更新时应使用系统 GUI 更新器或人工运行相应维护命令。

3.4 当前硬件不存在但仍启动的服务

虚拟机通常没有指纹设备、真实硬件传感器或 CPU frequency 接口,但相关服务仍可能被默认启用。它们无法提供实际能力,只会产生探测、模块加载或超时等待。

项目通过 /devlsusb/sys 探测硬件,只在确认设备不存在时处理相应服务,避免把虚拟机策略直接套用到真实笔记本。

4. 分层优化方案

所有候选项都在 scripts/auto-optimize.sh 中以固定白名单维护,不会扫描系统后自行猜测和关闭未知服务。

层级 优化对象 处理目的 实现条件
Tier 1 apt-daily.timerapt-daily-upgrade.timerkylin-source-update-*timermanager.timermotd-news.timerdpkg-db-backup.timere2scrub_all.timer 减少开机后维护任务对桌面加载的 I/O 和 CPU 竞争 单元存在时加入计划
Tier 2 dnsmasq.service 从图形关键路径中移除冗余 DNS 等待 必须先确认系统不依赖 dnsmasq
Tier 2 NetworkManager-wait-online.service 避免桌面登录等待所有网络接口完全在线 桌面不依赖 network-online 完成语义
Tier 2 samba-ad-dc.service 避免普通客户端启动 AD 域控能力 当前机器不是 AD 域控制器
Tier 2 nvmf-autoconnect.servicenvmefc-boot-connections.service 避免无 NVMe-oF 环境中的空转 当前机器不使用 NVMe-oF
Tier 3 biometric-authentication.service 避免无生物识别设备时启动认证服务 未探测到指纹或生物识别设备
Tier 3 lm-sensors.service 避免虚拟机中加载无意义的硬件传感器 未探测到真实 hwmon 传感器
Tier 3 loadcpufreq.servicecpufrequtils.service 避免无 cpufreq 接口时初始化调频服务 /sys/devices/system/cpu/cpu0/cpufreq 不存在
Aggressive bluetooth.serviceukui-bluetooth.service 在确认无蓝牙设备的 VM 中进一步裁剪 仅显式使用 --aggressive 且未探测到蓝牙时

主实验只使用默认安全档,不使用 --aggressive。以下关键能力不在优化白名单中:

  • 显示管理器:LightDM、GDM、SDDM;
  • 系统基础:dbus、polkit、accounts-daemon;
  • 网络与解析:NetworkManager、systemd-resolved;
  • 桌面与会话:UKUI、GNOME 核心组件;
  • 存储和虚拟机能力:udisks2、open-vm-tools;
  • 启动画面和系统框架:plymouth、ostree、kysdk 核心服务。

5. 优化器的实现机制

5.1 参数与执行模式

auto-optimize.sh 支持以下模式:

参数 行为
无参数 应用 Tier 1、Tier 2 和硬件探测命中的 Tier 3
--dry-run 输出探测结果和计划,不停止或 mask 任何服务
--aggressive 在默认计划上增加无蓝牙硬件时的蓝牙服务裁剪
--revert 读取最近一次 round_<N>/manifest.txt 并逐项 unmask
--help 输出脚本说明

--dry-run 外,应用和还原都要求 root 权限。脚本首先通过 systemd-detect-virt 获取虚拟化类型,再执行以下硬件探测:

  • has_biometric:检查 /devlsusb/sys/class/fingerprint
  • has_cpufreq:检查 CPU 的 cpufreq sysfs 目录;
  • has_bluetooth:检查 /sys/class/bluetooth
  • has_sensors:检查 hwmon 设备名称是否属于真实温度或电压传感器。

5.2 计划构建与跨发行版过滤

脚本使用 PLAN 数组保存“单元名 + 原因”。Tier 1 和 Tier 2 先进入候选计划,Tier 3 只有在硬件探测不通过时才加入。

执行每一项前,脚本调用 systemctl list-unit-files 检查单元是否存在。不存在的 openKylin 特有单元会显示:

跳过 <unit> (本机不存在)

这一机制使相同脚本可以在 Ubuntu 等发行版上运行,而不会因为缺少 kylin-source-update-* 等单元而失败或创建无效配置。

5.3 应用、审计和状态记录

对于存在且通过人工确认的单元,脚本执行以下操作:

  1. 读取并输出当前 enabledactive 状态;
  2. 将单元名写入 optimizations/round_<N>/manifest.txt
  3. 将优化前状态写入 optimizations/round_<N>/pre-state.txt
  4. 停止当前单元;
  5. 使用 systemctl mask 阻止其再次由依赖或 timer 自动启动;
  6. 执行 systemctl daemon-reload
  7. 保存优化前的 systemd-analyze blame,用于审计和问题定位。

脚本只使用 stop、mask 和 unmask,不删除 unit 文件,也不直接修改发行版提供的 systemd 配置文件。

5.4 还原机制

执行以下命令时:

sudo ./scripts/auto-optimize.sh --revert

脚本查找最新的 optimizations/round_<N>/manifest.txt,对其中每个单元执行 systemctl unmask,然后执行 daemon-reloadpre-state.txt 保留优化前状态,供人工复核。还原后应重启并重新运行健康检查,确认服务由原有依赖关系正常拉起。

6. 测量脚本的实现机制

measure-boot.sh 是只读脚本,每次执行都会创建独立目录:

optimizations/<标签>_<时间戳>/

脚本首先采集完整原始证据:

  • summary.txt:systemd 启动总览;
  • blame.txt:各服务自身启动耗时;
  • critical-chain.txt:默认启动目标关键依赖链;
  • critical-chain-graphical.txt:图形目标关键依赖链;
  • enabled-units.txt:当前启用的 unit 快照;
  • boot-plot.svg:完整 systemd 启动时序图。

随后解析 systemd-analyze 输出,并通过 journalctl -b -o short-monotonic 获取本次启动中各事件的首次出现时间。

6.1 UKUI 与 GNOME 自动适配

脚本运行时检查 gnome-shell

  • 如果存在,选择 GNOME profile,使用 gnome-sessiongnome-shell、Nautilus/DING 和 ibus/fcitx5 判断桌面可用;
  • 如果不存在,选择 UKUI profile,使用 ukui-sessionukui-panel、Peony 和 fcitx5 判断桌面可用。

greeter 检测同时兼容日志中的 greeterlightdmgdm 标记;显示管理器健康检查兼容 LightDM、GDM/GDM3 和 SDDM。KDE、Xfce、Deepin 等其他桌面需要根据实际进程扩展 profile。

6.2 桌面可用时间计算

脚本对每个桌面核心组件查找本次启动日志中的首次出现时间,并取最大值作为 DESKTOP_READY_MONO_S。这是因为只有最晚出现的核心组件也已经启动,才能认为桌面达到最小可用状态。

随后计算:

STAGE2_DELTA_S = DESKTOP_READY_MONO_S - SESSION_MONO_S

最终将所有指标写入机器可读的 metrics.env,并将时间线与健康检查写入 report.txt

6.3 功能健康检查

每轮测量都检查以下能力:

  • 显示管理器;
  • dbus 系统总线;
  • NetworkManager;
  • systemd-resolved;
  • UKUI 或 GNOME 会话;
  • 任务栏、桌面 Shell 和文件能力;
  • fcitx5 或 ibus 输入法;
  • PulseAudio 或 PipeWire 声音服务。

任何 optimized 轮次出现 [FAIL] 时,都不能直接作为有效优化结果。应先执行还原、定位原因并重新测试。

7. 对比、汇总和可视化实现

compare-boot.sh 读取两个结果目录中的 metrics.env,对每个指标计算:

绝对变化 = optimized - baseline
百分比变化 = (optimized - baseline) / baseline * 100%

对于启动耗时指标,结果为负数表示优化后更快。该脚本适合查看单轮差异,但正式结论使用多轮中位数。

generate-test-assets.py 不依赖第三方 Python 库,主要完成以下工作:

  1. 递归读取 test-results/**/metrics.env
  2. 根据目录名识别环境、baseline/optimized 和轮次;
  3. 汇总每轮原始值到 raw_runs.csv
  4. 按环境和阶段计算中位数并写入 summary.md
  5. 生成关键路径图、启动时序图、结果对比图、稳定性图和迁移矩阵图。

generate-result-cards.py 为每轮测试生成一张 SVG 卡片,并为 openKylin、Ubuntu 分别生成环境汇总卡片。卡片同时展示核心指标、时间线、阶段拆解和健康检查,便于在报告或答辩中直接使用。

8. 为什么使用多轮中位数

虚拟机启动时间会受到宿主机 CPU 调度、磁盘缓存、后台任务和虚拟设备初始化影响。单轮数据可能出现明显长尾,因此项目采用以下规则:

  • baseline 和 optimized 各执行至少 3 轮;
  • 每轮都经历完整重启;
  • 保存全部原始轮次,不只保留最快结果;
  • 使用中位数作为主结论;
  • 如果某轮日志缺失或健康检查失败,保留证据并说明无效原因,不静默删除。

这种方法可以降低偶发抖动对结论的影响,同时保留稳定性分析所需的原始数据。

9. 安全边界与适用限制

[!WARNING] 优化命令只允许在本地测试虚拟机或经过明确评估的实验环境执行。禁止在生产、线上、预发、灰度或承载真实业务的机器执行。应用前必须先运行 --dry-run 并人工确认每个候选项。

以下场景不得直接应用默认计划:

  • 本机实际使用 dnsmasq 提供 DNS、DHCP 或虚拟网络;
  • 本机是 Samba AD 域控制器;
  • 本机使用 NVMe-oF;
  • 登录、挂载或业务服务要求 network-online.target 完成;
  • 机器使用自动 timer 完成必须执行的补丁、审计或维护任务;
  • 硬件探测结果与实际设备不一致;
  • 无法确认目标环境是否为测试环境。

推荐执行流程:

# 1. 只读采集 baseline
./scripts/measure-boot.sh baseline

# 2. 查看计划,不修改系统
./scripts/auto-optimize.sh --dry-run

# 3. 人工确认后,在本地测试 VM 应用安全档
sudo ./scripts/auto-optimize.sh
sudo reboot

# 4. 复测并对比
./scripts/measure-boot.sh optimized
./scripts/compare-boot.sh <baseline目录> <optimized目录>

# 5. 如有异常则还原并重启
sudo ./scripts/auto-optimize.sh --revert
sudo reboot

10. 优化收益与实现之间的对应关系

观察指标 主要优化来源 解释
Userspace 缩短 移除冗余和不适用服务 减少 systemd 用户空间需要启动或等待的单元
graphical.target 提前 dnsmasq 解耦、移除 wait-online 等待 缩短图形目标的最长依赖链
greeter 提前 减少早期服务和资源竞争 显示管理器更早获得 CPU、I/O 和依赖条件
登录到桌面缩短 关闭启动后集中触发的维护 timer 减少 UKUI/GNOME 组件加载期间的资源竞争
Kernel 基本不变 本方案不修改内核和 initramfs 证明主要收益来自 userspace,而非改变计时口径
迁移环境基本持平 不适用项自动跳过 证明脚本不会为了追求数字强行关闭其他发行版的服务

本方案的核心不是“关闭尽可能多的服务”,而是只处理经过依赖分析确认的冗余等待、当前环境不适用的能力和与桌面加载竞争的后台任务,同时使用功能健康检查证明优化没有突破桌面系统的可用性边界。

迁移测试与量化分析材料

本项目在 openKylin 虚拟机和 Ubuntu Desktop 虚拟机上完成了优化方案验证,用来证明:

  • openKylin 主环境中优化前后确实有量化收益;
  • 优化后图形登录、桌面、网络、DNS、输入法、声音等基础能力仍可用;
  • 同一套脚本迁移到 Ubuntu 时可以运行,并能自动跳过 openKylin 特有或本机不存在的服务;
  • 结果不是单次测试,而是 baseline / optimized 各 3 轮测试后取中位数。

新增材料说明

材料 路径 用途 建议看什么
虚拟机测试执行清单 docs/虚拟机测试执行清单.md 记录如何在 openKylin / Ubuntu VM 上复现实验,包括 baseline、dry-run、优化、复测、汇总 看测试步骤、计时口径、健康检查要求
迁移测试与量化分析报告 docs/迁移测试与量化分析.md 测试验证主报告,包含测试环境、三轮中位数、关键路径、时序、迁移测试和结论 优先看 openKylin 三轮中位数、Ubuntu 迁移结论、最终结论
openKylin 原始测试证据 test-results/openkylin/ 保存 openKylin VM 的 baseline 3 轮、optimized 3 轮、环境配置、dry-run 计划和优化清单 environment.txt、每个 run 的 report.txtcomponent-health.txtmetrics.env
Ubuntu 原始测试证据 test-results/ubuntu/ 保存 Ubuntu Desktop VM 的迁移测试证据,包括环境配置、baseline/optimized 各 3 轮和优化清单 environment.txtauto-optimize-dry-run.txt、每轮 component-health.txt
汇总表 test-results/summary/summary.md 汇总 openKylin / Ubuntu 的 baseline 与 optimized 中位数 看 systemd 总启动、graphical.target、桌面可用时间的前后变化
原始 CSV test-results/summary/raw_runs.csv 所有单轮测试的机器可读指标,便于重新画图或放入表格 看每一轮的原始数值和波动情况
关键路径/时序/结果图 figures/boot-analysis/ 面向报告/PPT 的核心分析图 critical_path_openkylin.svgboot_sequence_openkylin.svgtest_results_summary.svg
每轮测试卡片 figures/test-cards/ 把每一次测试做成通俗易懂的图片卡片,适合答辩展示 看每个 *_run*_card.svgopenkylin_summary_card.svgubuntu_summary_card.svg
汇总与出图脚本 scripts/generate-test-assets.py 自动读取 test-results/**/metrics.env,刷新汇总表和核心分析图 重跑测试后执行它刷新 summary.mdfigures/boot-analysis/
测试卡片生成脚本 scripts/generate-result-cards.py 自动生成每轮测试卡片和环境汇总卡片 重跑测试后执行它刷新 figures/test-cards/

关键结论速览

openKylin VM 三轮中位数显示:

指标 优化前 优化后 变化
systemd 总启动 10.087s 7.576s -2.511s (-24.9%)
graphical.target 4.561s 3.371s -1.190s (-26.1%)
开机到桌面可用 17.131s 15.217s -1.914s (-11.2%)
登录到桌面可用 9.922s 8.612s -1.310s (-13.2%)

Ubuntu Desktop VM 迁移测试显示:性能基本持平,但优化器能安全运行,openKylin 特有项会自动跳过,优化后桌面、网络、DNS、输入法、声音等健康检查全部正常。这部分主要证明方案的迁移复用能力和安全边界。

如何刷新图表

如果重新跑了 VM 测试,把新的 metrics.envreport.txtcomponent-health.txt 等结果放入 test-results/<环境>/<阶段_runN>/ 后,运行:

刷新汇总表和核心分析图:

python3 scripts/generate-test-assets.py

刷新每轮测试卡片:

python3 scripts/generate-result-cards.py
关于
6.0 MB
邀请码
    Gitlink(确实开源)
  • 加入我们
  • 官网邮箱:gitlink@ccf.org.cn
  • QQ群
  • QQ群
  • 公众号
  • 公众号

版权所有:中国计算机学会技术支持:开源发展技术委员会
京ICP备13000930号-9 京公网安备 11010802047560号