PostgreSQL Source Code git master
Loading...
Searching...
No Matches
gha_ccache_decide.py
Go to the documentation of this file.
1#!/usr/bin/env python3
2
3import os
4import re
5import shutil
6import subprocess
7
8def run(cmd, check=True):
9 return subprocess.run(
10 cmd,
11 check=check,
12 text=True,
13 stdout=subprocess.PIPE,
14 stderr=subprocess.STDOUT,
15 ).stdout
16
18 out = run(["ccache", "--print-stats"])
19 hits = 0
20 misses = 0
21
22 for line in out.splitlines():
23 line = line.strip()
24 m = re.match(r"^local_storage_hit\s+(\d+)$", line)
25 if m:
26 hits = int(m.group(1))
27 continue
28 m = re.match(r"^local_storage_miss\s+(\d+)$", line)
29 if m:
30 misses = int(m.group(1))
31 continue
32
33 return hits, misses
34
35def append_github_output(key, value):
36 output_path = os.environ["GITHUB_OUTPUT"]
37 with open(output_path, "a", encoding="utf-8") as f:
38 f.write(f"{key}={value}\n")
39
40def main():
41 on_default_branch = os.environ["ON_DEFAULT_BRANCH"] == "true"
42
43 # Decide the target hit percentage below which we decide to upload a new
44 # cache. On non-default branches a few misses aren't that bad. But, as the
45 # caches of the default branch are shared with all branches, it's worth
46 # aiming for a higher ratio there.
47 target_rate = 95 if on_default_branch else 80
48
49 # Log ccache stats, useful for more in-depth understanding. To avoid
50 # swamping the output, collapse it in a group.
51 print("::group::ccache_stats")
52 print(run(["ccache", "-s", "-vv"]))
53 print("::endgroup::")
54
55 # compute cache hit ratio
56 hits, misses = parse_ccache_stats()
57 total = hits + misses
58 hit_pct = int((hits / total) * 100) if total > 0 else 100
59
60 print(f"hits: {hits}, misses: {misses}, hit_pct: {hit_pct}, target rate: {target_rate}")
61
62 # If the cache hit ratio was high, or the absolute number of misses
63 # (e.g. in case of a failed build) was low, there is no point in
64 # generating a new cache entry. We have limited cache space.
65 if hit_pct >= target_rate:
66 print(f"hit rate {hit_pct} is above target of {target_rate}, skip creating new cache entry")
67 should_save = False
68 elif misses <= 10:
69 print(f"only {misses} misses, skip creating new cache entry")
70 should_save = False
71 else:
72 print(f"hit rate {hit_pct} is below target of {target_rate}, create new cache entry")
73 should_save = True
74
75 append_github_output("should_save", str(should_save).lower())
76
77 if not should_save:
78 return 0
79
80 # It's not worth persisting old cache entries (e.g. from before a
81 # change to a central header, or from the default branch if this
82 # branch differs a lot). Therefore evict ccache entries that are a
83 # bit older. The cutoff here is fairly arbitrary, it could
84 # probably be improved.
85 print("::group::ccache_shrink")
86 print(run(["ccache", "--evict-older-than", f"{45*60}s"]))
87 print(run(["ccache", "-X", "10"]))
88
89 # Don't store ccache stats, otherwise we'd need to reset the cache access
90 # data after restoring the cache in the next run, to be able to get the
91 # hit ratio of the CI run.
92 print(run(["ccache", "-z"]))
93 print("::endgroup::")
94
95 # Before continuing, try to kill all ccache instances, otherwise
96 # it's possible that on cancellations there is still running
97 # ccaches that cause the upload to fail.
98 if shutil.which("killall"):
99 print(run(["killall", "ccache"], check=False))
100
101 return 0
102
103if __name__ == "__main__":
104 exit(main())
void print(const void *obj)
Definition print.c:36
const char * str
append_github_output(key, value)
run(cmd, check=True)
Datum lower(PG_FUNCTION_ARGS)
static int fb(int x)