OpenHarmony 编译加速:ccache 使用指南

概述

ccache(compiler cache)是一个编译缓存工具,通过缓存编译结果来加速重复编译。OpenHarmony 构建系统通过 --ccache 参数原生支持 ccache。


1. 工作原理

复制代码
源码编译请求
    │
    ▼
ccache 计算 hash(源码内容 + 编译参数 + 编译器版本 + 头文件)
    │
    ├─ 命中(Hit)→ 直接复制缓存的 .o 文件(毫秒级)
    │
    └─ 未命中(Miss)→ 调用真实 clang 编译
                         → 把编译结果存入缓存
                         → 返回 .o 文件

hash 计算包含的因素

因素 说明
源文件内容 文件本身的 hash
预处理后内容 展开所有 #include 和宏后的结果
编译参数 -O2-DDEBUG 等所有 flags
编译器版本 clang 15.0.4 的二进制 hash
目标架构 --target=arm-linux-ohos

任何一项变化都会导致 cache miss。


2. 使用方法

基本用法

bash 复制代码
cd v6.1-release

# 带 ccache 编译
./build.sh --product-name rk3568 --ccache

# 不带 ccache 编译
./build.sh --product-name rk3568

查看缓存统计

bash 复制代码
ccache -s

输出示例:

复制代码
Cacheable calls:   31469 / 31484 (99.95%)
  Hits:             1180 / 31469 ( 3.75%)     ← 命中次数
    Direct:          801 /  1180 (67.88%)     ← 直接命中(最快)
    Preprocessed:    379 /  1180 (32.12%)     ← 预处理后命中
  Misses:          30289 / 31469 (96.25%)     ← 未命中(需要真实编译)
Local storage:
  Cache size (GB):   3.7 / 100.0 ( 3.75%)    ← 缓存占用

常用命令

bash 复制代码
# 查看统计信息
ccache -s

# 清空统计计数(不清缓存)
ccache -z

# 清空所有缓存
ccache -C

# 设置缓存大小上限
ccache -M 20G

# 查看当前配置
ccache -p

# 查看缓存目录
ccache -k cache_dir

3. 命中模式

ccache 有两种命中模式:

Direct 模式(最快)

复制代码
源文件 hash + 编译参数 → 直接查找缓存
  • 不需要运行预处理器
  • 速度最快(微秒级)
  • 要求源文件和所有头文件都未变化

Preprocessed 模式(次快)

复制代码
源文件 → 预处理器展开 → 预处理结果 hash → 查找缓存
  • 需要运行预处理器(毫秒级)
  • 能处理 __TIME____DATE__ 等宏变化的情况
  • 当 Direct 模式 miss 时自动回退到此模式

4. 性能对比

不同场景下的编译耗时(24 核 / 32GB,RK3568)

编译场景 不加 ccache 加 ccache
首次全量编译 ~3 小时 ~3 小时 10 分钟(略慢,写缓存开销)
无改动重编 ~2 小时 50 分钟 ~10-20 分钟
改 1 个 .cpp ~30-60 分钟 ~2-5 分钟
改 1 个公共头文件 ~2 小时 ~30-60 分钟
切换分支后编译 全量重编 大部分命中缓存
架构切换(arm→arm64) 全量重编 全量重编(hash 不同)

命中率变化趋势

编译次数 预期命中率 说明
第 1 次 0-5% 缓存为空,几乎全 miss
第 2 次(无改动) 95-99% 几乎全部命中
第 2 次(小改动) 90-95% 仅受影响文件 miss
第 2 次(改公共头文件) 30-70% 包含该头文件的所有源文件 miss

5. 配置优化

缓存目录

bash 复制代码
# 默认位置
~/.ccache/

# 自定义位置(建议放在 SSD 上)
export CCACHE_DIR=/data/ccache

推荐配置

bash 复制代码
# 增大缓存上限(OpenHarmony 全量编译约需 5-10GB)
ccache -M 20G

# 启用压缩(节省磁盘,略增 CPU 开销)
ccache -o compression=true
ccache -o compression_level=3

# 设置最大文件数(避免小文件过多导致 inode 耗尽)
ccache -o max_files=0    # 0 表示不限制

配置文件

ccache 配置文件位于 ~/.config/ccache/ccache.conf

ini 复制代码
max_size = 20G
compression = true
compression_level = 3

6. 统计指标解读

复制代码
Cacheable calls:   31469 / 31484 (99.95%)
指标 含义
Cacheable calls 可缓存的编译调用占比(接近 100% 说明 ccache 覆盖了几乎所有编译)
Hits 命中次数(越高越好)
Direct hits 直接命中(最快路径)
Preprocessed hits 预处理后命中(次快)
Misses 未命中(需要真实编译并写入缓存)
Uncacheable 不可缓存的调用(如链接操作)
Errors 编译错误次数(不是 ccache 的错,是源码编译失败)
Cache size 当前缓存占用 / 上限

健康指标

指标 健康值 说明
命中率(非首次) > 80% 低于此值说明改动范围大或缓存被频繁淘汰
Direct hit 占比 > 60% 低于此值可能有 __TIME__ 等宏干扰
Cache size < 80% 上限 接近上限时旧缓存会被淘汰

7. 缓存失效的常见原因

原因 影响范围 解决方法
修改公共头文件 所有包含该头文件的源文件 miss 无法避免,这是正确行为
切换编译器版本 全部 miss 无法避免
切换目标架构(arm↔arm64) 全部 miss 无法避免(编译参数不同)
修改 GN 编译参数 受影响目标全部 miss 尽量避免频繁改 gn-args
缓存空间满被淘汰 最旧的缓存被删除 增大 max_size
清空了 out 目录 不影响 ccache(缓存在 ~/.ccache) 正常,ccache 仍有效

8. ccache 与 OpenHarmony 构建系统的集成

build.sh 中的实现

--ccache 参数会让构建系统在调用 clang 前插入 ccache:

复制代码
# 不加 --ccache
clang --target=arm-linux-ohos -c foo.c -o foo.o

# 加 --ccache
ccache clang --target=arm-linux-ohos -c foo.c -o foo.o

GN 通过设置 cc_wrapper = "ccache" 实现这一点。

与 ninja 的配合

复制代码
ninja 调度编译任务(并行)
  → 每个任务调用 ccache clang ...
    → ccache 查缓存
      → 命中:直接返回(不占 CPU)
      → 未命中:调用 clang 编译(占 CPU)

命中缓存的任务几乎不消耗 CPU,所以 --jobs=N 可以设得更高。


9. 最佳实践

日常开发

bash 复制代码
# 始终加 --ccache
./build.sh --product-name rk3568 --ccache

# 编译前清零统计,编译后查看本次命中率
ccache -z
./build.sh --product-name rk3568 --ccache
ccache -s

清除编译产物但保留缓存

bash 复制代码
# 只删 out 目录(ccache 不受影响)
rm -rf out/rk3568

# 重新编译时大部分会命中缓存
./build.sh --product-name rk3568 --ccache

CI/CD 环境

bash 复制代码
# 持久化 ccache 目录到共享存储
export CCACHE_DIR=/shared/ccache/rk3568

# 设置较大缓存
ccache -M 50G

# 多分支共享缓存(相同源文件 + 相同参数 = 命中)

10. 什么时候不该用 ccache

场景 原因
磁盘空间极度紧张(< 10GB) 缓存会占用额外空间
调试编译器本身的问题 需要看到真实的编译过程
编译器版本频繁切换 缓存基本不命中,纯浪费 IO
只编译一次就丢弃的环境 写缓存的开销无法回收

11. 总结

结论 说明
默认就加 --ccache 除极少数场景外,加 ccache 只有好处
首次编译略慢 写缓存有 5-10% 开销,可忽略
后续编译大幅加速 命中率 80%+ 时,编译时间缩短 5-10 倍
不影响编译正确性 hash 严格匹配,不会返回错误的缓存
rm -rf out/ 兼容 缓存独立于编译产物目录
相关推荐
●VON1 小时前
AtomGit Flutter鸿蒙客户端:OAuth2认证与登录
flutter·华为·跨平台·harmonyos·鸿蒙
小菜鸟学开发1 小时前
OpenHarmony 编译资源复用指南
harmonyos
互联网散修1 小时前
鸿蒙实战:图片编辑器——涂鸦、撤回与保存功能
编辑器·harmonyos·涂鸦·图片编辑
●VON1 小时前
AtomGit Flutter鸿蒙客户端:Tab导航架构
flutter·华为·架构·harmonyos·鸿蒙
Swift社区2 小时前
鸿蒙 PC 文件共享:分布式机制 + Demo 实现
分布式·华为·harmonyos
ShallowLin10 小时前
【HarmonyOS闯关习题】——DevEco Studio的使用
华为·harmonyos
科技与数码12 小时前
鸿蒙6.1小艺伴随式AI体验:让阅读效率翻倍
人工智能·华为·harmonyos
程序猿追12 小时前
棋盘上的博弈:我在 HarmonyOS 里塞了一个五子棋“大脑”
人工智能·华为·harmonyos