rickub/ci-benchpublic Fork 0
28dfdd8
Commits
Clone
git clone https://git.rickub.com/rickub/ci-bench.git
git clone ssh://git@rickub.com/rickub/ci-bench.git

Host key fingerprint (ed25519): SHA256:iycHnxEyq0Q7uyVpB7JlznP0G7JrTPXLYRcAU5CSLhc — verify it before your first connect.

bench: cache tier — actions/cache@v4.2.4 restore/save timed natively on both platforms, isolated CARGO_HOME warm armUnverified

Olivier Girardot committed 2026-09-13T15:02:52+02:00 Browse files
28dfdd8 parent: 6b67a7e
modified .github/workflows/bench.yml +63 -0
@@ -125,6 +125,69 @@ jobs:
125125 bench_skip java-guava "maven not available on runner"
126126 fi
127127
128+ # --- cache tier: each platform's NATIVE cache service, as users use it --
129+ # actions/cache restore/save split actions @ v4.2.4 — deliberately the
130+ # v4/node20 line (the action runs INSIDE the guest; v6 would measure node
131+ # absence, not cache). Identical key and paths on both platforms; v4 is
132+ # also the exact protocol generation rickub's cache service implements
133+ # (verified against the actions/cache@v4 client, web/ci_cache_api.go).
134+ # The cached build uses an ISOLATED CARGO_HOME + target dir so it measures
135+ # the warm path from cache alone — the earlier steps' registry downloads
136+ # cannot leak into it. First run on a lockfile change is a MISS (primes
137+ # the cache); the interleaved rounds then measure warm hits. `uses:`
138+ # steps cannot be wrapped by bench_step, so restore/save are timed via an
139+ # env-carried start stamp + a direct _bench_emit, with the hit flag as a
140+ # JSON boolean in the value field.
141+
142+ - name: stamp cache-restore start
143+ run: |
144+ source "${GITHUB_WORKSPACE:-$PWD}/scripts/emit_timing.sh"
145+ echo "CACHE_RESTORE_T0=$(_bench_now_iso)" >> "$GITHUB_ENV"
146+
147+ - name: cache restore (cargo)
148+ id: cache-restore
149+ uses: actions/cache/restore@0400d5f644dc74513175e3cd8d07132dd4860809 # v4.2.4
150+ with:
151+ path: |
152+ workloads/rust-build/.cargo-cached/registry
153+ workloads/rust-build/target-cached
154+ key: ci-bench-cached-rust-${{ hashFiles('workloads/rust-build/Cargo.lock') }}
155+
156+ - name: time cache restore
157+ run: |
158+ set -euo pipefail
159+ source "${GITHUB_WORKSPACE:-$PWD}/scripts/emit_timing.sh"
160+ if [ "${{ steps.cache-restore.outputs.cache-hit }}" = "true" ]; then hit=true; else hit=false; fi
161+ _bench_emit cache-restore-rust ok "$CACHE_RESTORE_T0" "$(_bench_now_iso)" "$hit" "cache_hit"
162+
163+ - name: rust cached build
164+ run: |
165+ set -euo pipefail
166+ source "${GITHUB_WORKSPACE:-$PWD}/scripts/emit_timing.sh"
167+ cd workloads/rust-build
168+ bench_step rust-cached-build env \
169+ CARGO_HOME="$PWD/.cargo-cached" CARGO_TARGET_DIR="$PWD/target-cached" \
170+ cargo build --manifest-path Cargo.toml
171+
172+ - name: stamp cache-save start
173+ run: |
174+ source "${GITHUB_WORKSPACE:-$PWD}/scripts/emit_timing.sh"
175+ echo "CACHE_SAVE_T0=$(_bench_now_iso)" >> "$GITHUB_ENV"
176+
177+ - name: cache save (cargo)
178+ uses: actions/cache/save@0400d5f644dc74513175e3cd8d07132dd4860809 # v4.2.4
179+ with:
180+ path: |
181+ workloads/rust-build/.cargo-cached/registry
182+ workloads/rust-build/target-cached
183+ key: ci-bench-cached-rust-${{ hashFiles('workloads/rust-build/Cargo.lock') }}
184+
185+ - name: time cache save
186+ run: |
187+ set -euo pipefail
188+ source "${GITHUB_WORKSPACE:-$PWD}/scripts/emit_timing.sh"
189+ _bench_emit cache-save-rust ok "$CACHE_SAVE_T0" "$(_bench_now_iso)"
190+
128191 - name: probe runner
129192 run: bash workloads/probe/probe.sh
130193
@@ -125,6 +125,69 @@ jobs:
125 bench_skip java-guava "maven not available on runner"125 bench_skip java-guava "maven not available on runner"
126 fi126 fi
127 127
128+ # --- cache tier: each platform's NATIVE cache service, as users use it --
129+ # actions/cache restore/save split actions @ v4.2.4 — deliberately the
130+ # v4/node20 line (the action runs INSIDE the guest; v6 would measure node
131+ # absence, not cache). Identical key and paths on both platforms; v4 is
132+ # also the exact protocol generation rickub's cache service implements
133+ # (verified against the actions/cache@v4 client, web/ci_cache_api.go).
134+ # The cached build uses an ISOLATED CARGO_HOME + target dir so it measures
135+ # the warm path from cache alone — the earlier steps' registry downloads
136+ # cannot leak into it. First run on a lockfile change is a MISS (primes
137+ # the cache); the interleaved rounds then measure warm hits. `uses:`
138+ # steps cannot be wrapped by bench_step, so restore/save are timed via an
139+ # env-carried start stamp + a direct _bench_emit, with the hit flag as a
140+ # JSON boolean in the value field.
141+
142+ - name: stamp cache-restore start
143+ run: |
144+ source "${GITHUB_WORKSPACE:-$PWD}/scripts/emit_timing.sh"
145+ echo "CACHE_RESTORE_T0=$(_bench_now_iso)" >> "$GITHUB_ENV"
146+
147+ - name: cache restore (cargo)
148+ id: cache-restore
149+ uses: actions/cache/restore@0400d5f644dc74513175e3cd8d07132dd4860809 # v4.2.4
150+ with:
151+ path: |
152+ workloads/rust-build/.cargo-cached/registry
153+ workloads/rust-build/target-cached
154+ key: ci-bench-cached-rust-${{ hashFiles('workloads/rust-build/Cargo.lock') }}
155+
156+ - name: time cache restore
157+ run: |
158+ set -euo pipefail
159+ source "${GITHUB_WORKSPACE:-$PWD}/scripts/emit_timing.sh"
160+ if [ "${{ steps.cache-restore.outputs.cache-hit }}" = "true" ]; then hit=true; else hit=false; fi
161+ _bench_emit cache-restore-rust ok "$CACHE_RESTORE_T0" "$(_bench_now_iso)" "$hit" "cache_hit"
162+
163+ - name: rust cached build
164+ run: |
165+ set -euo pipefail
166+ source "${GITHUB_WORKSPACE:-$PWD}/scripts/emit_timing.sh"
167+ cd workloads/rust-build
168+ bench_step rust-cached-build env \
169+ CARGO_HOME="$PWD/.cargo-cached" CARGO_TARGET_DIR="$PWD/target-cached" \
170+ cargo build --manifest-path Cargo.toml
171+
172+ - name: stamp cache-save start
173+ run: |
174+ source "${GITHUB_WORKSPACE:-$PWD}/scripts/emit_timing.sh"
175+ echo "CACHE_SAVE_T0=$(_bench_now_iso)" >> "$GITHUB_ENV"
176+
177+ - name: cache save (cargo)
178+ uses: actions/cache/save@0400d5f644dc74513175e3cd8d07132dd4860809 # v4.2.4
179+ with:
180+ path: |
181+ workloads/rust-build/.cargo-cached/registry
182+ workloads/rust-build/target-cached
183+ key: ci-bench-cached-rust-${{ hashFiles('workloads/rust-build/Cargo.lock') }}
184+
185+ - name: time cache save
186+ run: |
187+ set -euo pipefail
188+ source "${GITHUB_WORKSPACE:-$PWD}/scripts/emit_timing.sh"
189+ _bench_emit cache-save-rust ok "$CACHE_SAVE_T0" "$(_bench_now_iso)"
190+
128 - name: probe runner191 - name: probe runner
129 run: bash workloads/probe/probe.sh192 run: bash workloads/probe/probe.sh
130 193
modified .rickub/workflows/bench.yml +63 -0
@@ -134,6 +134,69 @@ jobs:
134134 bench_skip java-guava "maven not available on runner"
135135 fi
136136
137+ # --- cache tier: each platform's NATIVE cache service, as users use it --
138+ # actions/cache restore/save split actions @ v4.2.4 — deliberately the
139+ # v4/node20 line (the action runs INSIDE the guest; v6 would measure node
140+ # absence, not cache). Identical key and paths on both platforms; v4 is
141+ # also the exact protocol generation rickub's cache service implements
142+ # (verified against the actions/cache@v4 client, web/ci_cache_api.go).
143+ # The cached build uses an ISOLATED CARGO_HOME + target dir so it measures
144+ # the warm path from cache alone — the earlier steps' registry downloads
145+ # cannot leak into it. First run on a lockfile change is a MISS (primes
146+ # the cache); the interleaved rounds then measure warm hits. `uses:`
147+ # steps cannot be wrapped by bench_step, so restore/save are timed via an
148+ # env-carried start stamp + a direct _bench_emit, with the hit flag as a
149+ # JSON boolean in the value field.
150+
151+ - name: stamp cache-restore start
152+ run: |
153+ source "${GITHUB_WORKSPACE:-$PWD}/scripts/emit_timing.sh"
154+ echo "CACHE_RESTORE_T0=$(_bench_now_iso)" >> "$GITHUB_ENV"
155+
156+ - name: cache restore (cargo)
157+ id: cache-restore
158+ uses: actions/cache/restore@0400d5f644dc74513175e3cd8d07132dd4860809 # v4.2.4
159+ with:
160+ path: |
161+ workloads/rust-build/.cargo-cached/registry
162+ workloads/rust-build/target-cached
163+ key: ci-bench-cached-rust-${{ hashFiles('workloads/rust-build/Cargo.lock') }}
164+
165+ - name: time cache restore
166+ run: |
167+ set -euo pipefail
168+ source "${GITHUB_WORKSPACE:-$PWD}/scripts/emit_timing.sh"
169+ if [ "${{ steps.cache-restore.outputs.cache-hit }}" = "true" ]; then hit=true; else hit=false; fi
170+ _bench_emit cache-restore-rust ok "$CACHE_RESTORE_T0" "$(_bench_now_iso)" "$hit" "cache_hit"
171+
172+ - name: rust cached build
173+ run: |
174+ set -euo pipefail
175+ source "${GITHUB_WORKSPACE:-$PWD}/scripts/emit_timing.sh"
176+ cd workloads/rust-build
177+ bench_step rust-cached-build env \
178+ CARGO_HOME="$PWD/.cargo-cached" CARGO_TARGET_DIR="$PWD/target-cached" \
179+ cargo build --manifest-path Cargo.toml
180+
181+ - name: stamp cache-save start
182+ run: |
183+ source "${GITHUB_WORKSPACE:-$PWD}/scripts/emit_timing.sh"
184+ echo "CACHE_SAVE_T0=$(_bench_now_iso)" >> "$GITHUB_ENV"
185+
186+ - name: cache save (cargo)
187+ uses: actions/cache/save@0400d5f644dc74513175e3cd8d07132dd4860809 # v4.2.4
188+ with:
189+ path: |
190+ workloads/rust-build/.cargo-cached/registry
191+ workloads/rust-build/target-cached
192+ key: ci-bench-cached-rust-${{ hashFiles('workloads/rust-build/Cargo.lock') }}
193+
194+ - name: time cache save
195+ run: |
196+ set -euo pipefail
197+ source "${GITHUB_WORKSPACE:-$PWD}/scripts/emit_timing.sh"
198+ _bench_emit cache-save-rust ok "$CACHE_SAVE_T0" "$(_bench_now_iso)"
199+
137200 - name: probe runner
138201 run: bash workloads/probe/probe.sh
139202
@@ -134,6 +134,69 @@ jobs:
134 bench_skip java-guava "maven not available on runner"134 bench_skip java-guava "maven not available on runner"
135 fi135 fi
136 136
137+ # --- cache tier: each platform's NATIVE cache service, as users use it --
138+ # actions/cache restore/save split actions @ v4.2.4 — deliberately the
139+ # v4/node20 line (the action runs INSIDE the guest; v6 would measure node
140+ # absence, not cache). Identical key and paths on both platforms; v4 is
141+ # also the exact protocol generation rickub's cache service implements
142+ # (verified against the actions/cache@v4 client, web/ci_cache_api.go).
143+ # The cached build uses an ISOLATED CARGO_HOME + target dir so it measures
144+ # the warm path from cache alone — the earlier steps' registry downloads
145+ # cannot leak into it. First run on a lockfile change is a MISS (primes
146+ # the cache); the interleaved rounds then measure warm hits. `uses:`
147+ # steps cannot be wrapped by bench_step, so restore/save are timed via an
148+ # env-carried start stamp + a direct _bench_emit, with the hit flag as a
149+ # JSON boolean in the value field.
150+
151+ - name: stamp cache-restore start
152+ run: |
153+ source "${GITHUB_WORKSPACE:-$PWD}/scripts/emit_timing.sh"
154+ echo "CACHE_RESTORE_T0=$(_bench_now_iso)" >> "$GITHUB_ENV"
155+
156+ - name: cache restore (cargo)
157+ id: cache-restore
158+ uses: actions/cache/restore@0400d5f644dc74513175e3cd8d07132dd4860809 # v4.2.4
159+ with:
160+ path: |
161+ workloads/rust-build/.cargo-cached/registry
162+ workloads/rust-build/target-cached
163+ key: ci-bench-cached-rust-${{ hashFiles('workloads/rust-build/Cargo.lock') }}
164+
165+ - name: time cache restore
166+ run: |
167+ set -euo pipefail
168+ source "${GITHUB_WORKSPACE:-$PWD}/scripts/emit_timing.sh"
169+ if [ "${{ steps.cache-restore.outputs.cache-hit }}" = "true" ]; then hit=true; else hit=false; fi
170+ _bench_emit cache-restore-rust ok "$CACHE_RESTORE_T0" "$(_bench_now_iso)" "$hit" "cache_hit"
171+
172+ - name: rust cached build
173+ run: |
174+ set -euo pipefail
175+ source "${GITHUB_WORKSPACE:-$PWD}/scripts/emit_timing.sh"
176+ cd workloads/rust-build
177+ bench_step rust-cached-build env \
178+ CARGO_HOME="$PWD/.cargo-cached" CARGO_TARGET_DIR="$PWD/target-cached" \
179+ cargo build --manifest-path Cargo.toml
180+
181+ - name: stamp cache-save start
182+ run: |
183+ source "${GITHUB_WORKSPACE:-$PWD}/scripts/emit_timing.sh"
184+ echo "CACHE_SAVE_T0=$(_bench_now_iso)" >> "$GITHUB_ENV"
185+
186+ - name: cache save (cargo)
187+ uses: actions/cache/save@0400d5f644dc74513175e3cd8d07132dd4860809 # v4.2.4
188+ with:
189+ path: |
190+ workloads/rust-build/.cargo-cached/registry
191+ workloads/rust-build/target-cached
192+ key: ci-bench-cached-rust-${{ hashFiles('workloads/rust-build/Cargo.lock') }}
193+
194+ - name: time cache save
195+ run: |
196+ set -euo pipefail
197+ source "${GITHUB_WORKSPACE:-$PWD}/scripts/emit_timing.sh"
198+ _bench_emit cache-save-rust ok "$CACHE_SAVE_T0" "$(_bench_now_iso)"
199+
137 - name: probe runner200 - name: probe runner
138 run: bash workloads/probe/probe.sh201 run: bash workloads/probe/probe.sh
139 202
modified README.md +18 -0
@@ -215,3 +215,21 @@ ClickHouse is deliberately absent: a full build needs dozens of cores and
215215 ClickHouse-scale tier needs a dedicated runner class, not a benchmark step.
216216 SQLite's amalgamation is the C/C++ stand-in: a real configure+make of one of
217217 the most deployed codebases on earth, reproducible from a pinned tarball.
218+
219+## Cache tier (round 3+)
220+
221+A controlled warm-path arm using each platform's NATIVE cache service exactly
222+as users consume it: `actions/cache@v4.2.4` restore/save split actions (the
223+v4/node20 line — the action runs inside the guest; v6 requires node24 and
224+would measure node absence on some runners, and v4 is the protocol generation
225+rickub's cache service implements), identical key (`hashFiles` of the pinned
226+Cargo.lock) and paths on both platforms.
227+
228+Design: the cached build uses an ISOLATED `CARGO_HOME` + target dir, so it
229+measures the warm path from cache alone — earlier steps' registry downloads
230+cannot leak into it. Metrics per run: `cache-restore-rust` (the cache
231+SERVICE's speed, with a hit/miss boolean in the value field),
232+`rust-cached-build` (warm build), `cache-save-rust` (upload). The cold arm is
233+the same workload without cache, already measured every round. First run
234+after a lockfile change is a miss and primes the cache; interleaved rounds
235+then measure warm hits.
@@ -215,3 +215,21 @@ ClickHouse is deliberately absent: a full build needs dozens of cores and
215 ClickHouse-scale tier needs a dedicated runner class, not a benchmark step.215 ClickHouse-scale tier needs a dedicated runner class, not a benchmark step.
216 SQLite's amalgamation is the C/C++ stand-in: a real configure+make of one of216 SQLite's amalgamation is the C/C++ stand-in: a real configure+make of one of
217 the most deployed codebases on earth, reproducible from a pinned tarball.217 the most deployed codebases on earth, reproducible from a pinned tarball.
218+
219+## Cache tier (round 3+)
220+
221+A controlled warm-path arm using each platform's NATIVE cache service exactly
222+as users consume it: `actions/cache@v4.2.4` restore/save split actions (the
223+v4/node20 line — the action runs inside the guest; v6 requires node24 and
224+would measure node absence on some runners, and v4 is the protocol generation
225+rickub's cache service implements), identical key (`hashFiles` of the pinned
226+Cargo.lock) and paths on both platforms.
227+
228+Design: the cached build uses an ISOLATED `CARGO_HOME` + target dir, so it
229+measures the warm path from cache alone — earlier steps' registry downloads
230+cannot leak into it. Metrics per run: `cache-restore-rust` (the cache
231+SERVICE's speed, with a hit/miss boolean in the value field),
232+`rust-cached-build` (warm build), `cache-save-rust` (upload). The cold arm is
233+the same workload without cache, already measured every round. First run
234+after a lockfile change is a miss and primes the cache; interleaved rounds
235+then measure warm hits.
modified push-times.json +22 -20
@@ -1,22 +1,24 @@
11 {
2- "github/34747021476-1-0baf736": "2026-09-13T08:10:23Z",
3- "github/34747558752-1-9990e0f": "2026-09-13T08:23:19.000Z",
4- "github/34747135670-1-1914eed": "2026-09-13T08:13:05.000Z",
5- "github/34747186494-1-09e7984": "2026-09-13T08:14:22.000Z",
6- "github/34747770747-1-35efc9c": "2026-09-13T08:28:27.000Z",
7- "github/34747992384-1-66a47c3": "2026-09-13T08:33:34.000Z",
8- "github/34747395033-1-8421335": "2026-09-13T08:19:29.000Z",
9- "github/34747825179-1-39ba5db": "2026-09-13T08:29:45.000Z",
10- "github/34747612020-1-fba04eb": "2026-09-13T08:24:37.000Z",
11- "github/34747344847-1-da2d24b": "2026-09-13T08:18:12.000Z",
12- "rickub/3-1-09e7984": "2026-09-13T08:15:40.000Z",
13- "rickub/2-1-1914eed": "2026-09-13T08:11:49.000Z",
14- "rickub/5-1-8421335": "2026-09-13T08:20:47.000Z",
15- "rickub/9-1-39ba5db": "2026-09-13T08:31:02.000Z",
16- "rickub/8-1-35efc9c": "2026-09-13T08:27:10.000Z",
17- "rickub/4-1-da2d24b": "2026-09-13T08:16:56.000Z",
18- "rickub/7-1-fba04eb": "2026-09-13T08:25:54.000Z",
19- "rickub/10-1-66a47c3": "2026-09-13T08:32:18.000Z",
20- "rickub/6-1-9990e0f": "2026-09-13T08:22:03.000Z",
21- "rickub/1-1-0baf736": "2026-09-13T08:10:15Z"
2+ "github/34749218316-1-7683a17": "2026-09-13T09:16:09Z",
3+ "github/34749658712-1-4c9fe4d": "2026-09-13T09:31:57.000Z",
4+ "github/34749753971-1-386c455": "2026-09-13T09:34:30.000Z",
5+ "github/34750047176-1-4a60b11": "2026-09-13T09:42:05.000Z",
6+ "github/34750152332-1-ea32c96": "2026-09-13T09:44:38.000Z",
7+ "github/34750423984-1-07cf2ad": "2026-09-13T09:52:14.000Z",
8+ "github/34750527899-1-5c18d17": "2026-09-13T09:54:47.000Z",
9+ "github/34750819327-1-acae4f9": "2026-09-13T10:02:23.000Z",
10+ "github/34750925882-1-1314292": "2026-09-13T10:04:55.000Z",
11+ "github/34751250473-1-777b256": "2026-09-13T10:12:30.000Z",
12+ "github/34751355186-1-c936d6f": "2026-09-13T10:15:03.000Z",
13+ "rickub/14-1-7683a17": "2026-09-13T09:16:06Z",
14+ "rickub/15-1-4c9fe4d": "2026-09-13T09:29:26.000Z",
15+ "rickub/16-1-386c455": "2026-09-13T09:37:02.000Z",
16+ "rickub/17-1-4a60b11": "2026-09-13T09:39:34.000Z",
17+ "rickub/18-1-ea32c96": "2026-09-13T09:47:10.000Z",
18+ "rickub/19-1-07cf2ad": "2026-09-13T09:49:42.000Z",
19+ "rickub/20-1-5c18d17": "2026-09-13T09:57:20.000Z",
20+ "rickub/21-1-acae4f9": "2026-09-13T09:59:51.000Z",
21+ "rickub/22-1-1314292": "2026-09-13T10:07:28.000Z",
22+ "rickub/23-1-777b256": "2026-09-13T10:09:59.000Z",
23+ "rickub/24-1-c936d6f": "2026-09-13T10:17:36.000Z"
2224 }
\ No newline at end of file
@@ -1,22 +1,24 @@
1 {1 {
2- "github/34747021476-1-0baf736": "2026-09-13T08:10:23Z",2+ "github/34749218316-1-7683a17": "2026-09-13T09:16:09Z",
3- "github/34747558752-1-9990e0f": "2026-09-13T08:23:19.000Z",3+ "github/34749658712-1-4c9fe4d": "2026-09-13T09:31:57.000Z",
4- "github/34747135670-1-1914eed": "2026-09-13T08:13:05.000Z",4+ "github/34749753971-1-386c455": "2026-09-13T09:34:30.000Z",
5- "github/34747186494-1-09e7984": "2026-09-13T08:14:22.000Z",5+ "github/34750047176-1-4a60b11": "2026-09-13T09:42:05.000Z",
6- "github/34747770747-1-35efc9c": "2026-09-13T08:28:27.000Z",6+ "github/34750152332-1-ea32c96": "2026-09-13T09:44:38.000Z",
7- "github/34747992384-1-66a47c3": "2026-09-13T08:33:34.000Z",7+ "github/34750423984-1-07cf2ad": "2026-09-13T09:52:14.000Z",
8- "github/34747395033-1-8421335": "2026-09-13T08:19:29.000Z",8+ "github/34750527899-1-5c18d17": "2026-09-13T09:54:47.000Z",
9- "github/34747825179-1-39ba5db": "2026-09-13T08:29:45.000Z",9+ "github/34750819327-1-acae4f9": "2026-09-13T10:02:23.000Z",
10- "github/34747612020-1-fba04eb": "2026-09-13T08:24:37.000Z",10+ "github/34750925882-1-1314292": "2026-09-13T10:04:55.000Z",
11- "github/34747344847-1-da2d24b": "2026-09-13T08:18:12.000Z",11+ "github/34751250473-1-777b256": "2026-09-13T10:12:30.000Z",
12- "rickub/3-1-09e7984": "2026-09-13T08:15:40.000Z",12+ "github/34751355186-1-c936d6f": "2026-09-13T10:15:03.000Z",
13- "rickub/2-1-1914eed": "2026-09-13T08:11:49.000Z",13+ "rickub/14-1-7683a17": "2026-09-13T09:16:06Z",
14- "rickub/5-1-8421335": "2026-09-13T08:20:47.000Z",14+ "rickub/15-1-4c9fe4d": "2026-09-13T09:29:26.000Z",
15- "rickub/9-1-39ba5db": "2026-09-13T08:31:02.000Z",15+ "rickub/16-1-386c455": "2026-09-13T09:37:02.000Z",
16- "rickub/8-1-35efc9c": "2026-09-13T08:27:10.000Z",16+ "rickub/17-1-4a60b11": "2026-09-13T09:39:34.000Z",
17- "rickub/4-1-da2d24b": "2026-09-13T08:16:56.000Z",17+ "rickub/18-1-ea32c96": "2026-09-13T09:47:10.000Z",
18- "rickub/7-1-fba04eb": "2026-09-13T08:25:54.000Z",18+ "rickub/19-1-07cf2ad": "2026-09-13T09:49:42.000Z",
19- "rickub/10-1-66a47c3": "2026-09-13T08:32:18.000Z",19+ "rickub/20-1-5c18d17": "2026-09-13T09:57:20.000Z",
20- "rickub/6-1-9990e0f": "2026-09-13T08:22:03.000Z",20+ "rickub/21-1-acae4f9": "2026-09-13T09:59:51.000Z",
21- "rickub/1-1-0baf736": "2026-09-13T08:10:15Z"21+ "rickub/22-1-1314292": "2026-09-13T10:07:28.000Z",
22+ "rickub/23-1-777b256": "2026-09-13T10:09:59.000Z",
23+ "rickub/24-1-c936d6f": "2026-09-13T10:17:36.000Z"
22 }24 }
\ No newline at end of file\ No newline at end of file