检查 ccache 调用是否是缓存命中
Check if a ccache call was a cache hit
作为我构建过程的一部分,我想获得有关构建时间的统计信息以及 ccache 是否在缓存中找到该项目。我知道 ccache -s
我可以在哪里比较以前和当前的缓存命中数。
但是,如果我有数百个并行编译线程 运行,统计数据不会告诉我哪个文件导致了命中。
ccache
的return代码是编译器的代码。有什么方法可以让 ccache 告诉我它是否成功?
有两种选择:
- 启用ccache日志文件:在配置(或环境变量
CCACHE_LOGFILE
)中设置log_file
为一个文件路径。然后你可以从日志数据中找出每次编译的结果。如果有许多并行的 ccache 调用(日志文件在所有调用之间共享,因此来自不同进程的日志记录将交错),这可能会有点乏味,但可以通过考虑每个日志行的 PID 部分来实现。
- 在ccache 3.5 及更新版本中,最好启用调试模式:在配置中设置
debug = true
(或环境变量CCACHE_DEBUG=1
)。 ccache 然后会将每个生成的目标文件的日志存储在 <objectfile>.ccache-log
中。在 ccache 手册的 Cache debugging 中阅读更多内容。
我写了一个 quick-n-dirty 脚本,它告诉我必须重建哪些文件以及缓存未命中率是多少:
示例输出(截断):
ccache hit: lib/expression/unary_minus_expression.cpp
ccache miss: lib/expression/in_expression.cpp
ccache miss: lib/expression/arithmetic_expression.cpp
=== 249 files, 248 cache misses (0.995984 %)===
脚本:
#!/usr/bin/env python3
from pathlib import Path
import re
import os
files = {}
for filename in Path('src').rglob('*.ccache-log'):
with open(filename, 'r') as file:
for line in file:
source_file_match = re.findall(r'Source file: (.*)', line)
if source_file_match:
source_file = source_file_match[0]
result_match = re.findall(r'Result: cache (.*)', line)
if result_match:
result = result_match[0]
files[source_file] = result
break
if len(files) == 0:
print("No *.ccache-log files found. Did you compile with ccache and the environment variable CCACHE_DEBUG=1?")
sys.exit(1)
common_path_prefix = os.path.commonprefix(list(files.keys()))
files_shortened = {}
misses = 0
for file in files:
shortened = file.replace(common_path_prefix, '')
if files[file] == 'miss':
misses += 1
print("ccache miss: %s" % (shortened))
print("\n=== %i files, %i cache misses (%f %%)===\n" % (len(files), misses, float(misses) / len(files) * 100))
请注意,这会考虑所有 ccache-log 文件,而不仅仅是上次构建的文件。如果您想要后者,只需先删除日志文件即可。
作为我构建过程的一部分,我想获得有关构建时间的统计信息以及 ccache 是否在缓存中找到该项目。我知道 ccache -s
我可以在哪里比较以前和当前的缓存命中数。
但是,如果我有数百个并行编译线程 运行,统计数据不会告诉我哪个文件导致了命中。
ccache
的return代码是编译器的代码。有什么方法可以让 ccache 告诉我它是否成功?
有两种选择:
- 启用ccache日志文件:在配置(或环境变量
CCACHE_LOGFILE
)中设置log_file
为一个文件路径。然后你可以从日志数据中找出每次编译的结果。如果有许多并行的 ccache 调用(日志文件在所有调用之间共享,因此来自不同进程的日志记录将交错),这可能会有点乏味,但可以通过考虑每个日志行的 PID 部分来实现。 - 在ccache 3.5 及更新版本中,最好启用调试模式:在配置中设置
debug = true
(或环境变量CCACHE_DEBUG=1
)。 ccache 然后会将每个生成的目标文件的日志存储在<objectfile>.ccache-log
中。在 ccache 手册的 Cache debugging 中阅读更多内容。
我写了一个 quick-n-dirty 脚本,它告诉我必须重建哪些文件以及缓存未命中率是多少:
示例输出(截断):
ccache hit: lib/expression/unary_minus_expression.cpp
ccache miss: lib/expression/in_expression.cpp
ccache miss: lib/expression/arithmetic_expression.cpp
=== 249 files, 248 cache misses (0.995984 %)===
脚本:
#!/usr/bin/env python3
from pathlib import Path
import re
import os
files = {}
for filename in Path('src').rglob('*.ccache-log'):
with open(filename, 'r') as file:
for line in file:
source_file_match = re.findall(r'Source file: (.*)', line)
if source_file_match:
source_file = source_file_match[0]
result_match = re.findall(r'Result: cache (.*)', line)
if result_match:
result = result_match[0]
files[source_file] = result
break
if len(files) == 0:
print("No *.ccache-log files found. Did you compile with ccache and the environment variable CCACHE_DEBUG=1?")
sys.exit(1)
common_path_prefix = os.path.commonprefix(list(files.keys()))
files_shortened = {}
misses = 0
for file in files:
shortened = file.replace(common_path_prefix, '')
if files[file] == 'miss':
misses += 1
print("ccache miss: %s" % (shortened))
print("\n=== %i files, %i cache misses (%f %%)===\n" % (len(files), misses, float(misses) / len(files) * 100))
请注意,这会考虑所有 ccache-log 文件,而不仅仅是上次构建的文件。如果您想要后者,只需先删除日志文件即可。