Skip to content

Commit 6907298

Browse files
authored
Merge pull request #117 from mxsm/codex/pr-004-layout-benchmark-artifacts
Feat: Add layout and benchmark artifacts
2 parents 90f72bf + ab3ef5c commit 6907298

7 files changed

Lines changed: 217 additions & 2 deletions

File tree

.github/workflows/ci.yaml

Lines changed: 13 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -10,8 +10,8 @@ env:
1010
CI: true
1111

1212
jobs:
13-
build:
14-
runs-on: ubuntu-latest
13+
build:
14+
runs-on: ${{ matrix.os }}
1515

1616
strategy:
1717
matrix:
@@ -50,3 +50,14 @@ jobs:
5050

5151
- name: Test
5252
run: cargo test --verbose --all-features
53+
54+
- name: Layout snapshot
55+
run: cargo test layout_snapshot --all-features -- --nocapture
56+
57+
- name: Upload layout artifacts
58+
if: always()
59+
uses: actions/upload-artifact@v4
60+
with:
61+
name: layout-${{ matrix.os }}-${{ matrix.rust }}
62+
path: target/layout-artifacts
63+
if-no-files-found: ignore

Cargo.toml

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -37,6 +37,10 @@ harness = false
3737
name = "comprehensive"
3838
harness = false
3939

40+
[[bench]]
41+
name = "layout"
42+
harness = false
43+
4044
[[bench]]
4145
name = "simd"
4246
harness = false

bench-results/README.md

Lines changed: 53 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,53 @@
1+
# Benchmark Artifacts
2+
3+
This directory defines the artifact layout for performance-sensitive changes.
4+
Generated benchmark output should be committed only when it is intentionally
5+
used as review evidence for a release or PR.
6+
7+
Recommended layout:
8+
9+
```text
10+
bench-results/
11+
layout/
12+
current.json
13+
v1.1.json
14+
v1.2.json
15+
v2-packed.json
16+
criterion/
17+
before/
18+
after/
19+
mq/
20+
topic.json
21+
properties.json
22+
remoting-header.json
23+
summaries/
24+
summary-v1.1-v1.2.md
25+
summary-v1.2-v2-packed.md
26+
```
27+
28+
Minimum metadata for generated JSON artifacts:
29+
30+
```json
31+
{
32+
"crate": "cheetah-string",
33+
"version": "1.1.0",
34+
"profile": "release",
35+
"target": "x86_64-unknown-linux-gnu",
36+
"rustc": "rustc 1.xx.x",
37+
"os": "linux",
38+
"cpu": "model name",
39+
"bench": "layout"
40+
}
41+
```
42+
43+
For local capture, run:
44+
45+
```bash
46+
scripts/bench-all.sh current
47+
```
48+
49+
On Windows PowerShell:
50+
51+
```powershell
52+
scripts/bench-all.ps1 current
53+
```

benches/layout.rs

Lines changed: 57 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,57 @@
1+
use cheetah_string::CheetahString;
2+
use std::env;
3+
use std::fs;
4+
use std::mem::{align_of, size_of};
5+
use std::path::PathBuf;
6+
7+
fn target_dir() -> PathBuf {
8+
env::var_os("CARGO_TARGET_DIR")
9+
.map(PathBuf::from)
10+
.unwrap_or_else(|| PathBuf::from("target"))
11+
}
12+
13+
fn layout_entry<T>(name: &str) -> String {
14+
format!(
15+
r#"{{"type":"{}","size":{},"align":{}}}"#,
16+
name,
17+
size_of::<T>(),
18+
align_of::<T>()
19+
)
20+
}
21+
22+
fn main() {
23+
let layouts = [
24+
layout_entry::<CheetahString>("CheetahString"),
25+
layout_entry::<Option<CheetahString>>("Option<CheetahString>"),
26+
layout_entry::<String>("String"),
27+
layout_entry::<Option<String>>("Option<String>"),
28+
layout_entry::<&str>("&str"),
29+
layout_entry::<Option<&str>>("Option<&str>"),
30+
layout_entry::<std::sync::Arc<str>>("Arc<str>"),
31+
layout_entry::<Option<std::sync::Arc<str>>>("Option<Arc<str>>"),
32+
];
33+
34+
let snapshot = format!(
35+
concat!(
36+
"{{\n",
37+
" \"crate\":\"cheetah-string\",\n",
38+
" \"profile\":\"bench\",\n",
39+
" \"target_arch\":\"{}\",\n",
40+
" \"target_os\":\"{}\",\n",
41+
" \"pointer_width\":\"{}\",\n",
42+
" \"layouts\":[\n {}\n ]\n",
43+
"}}\n"
44+
),
45+
env::consts::ARCH,
46+
env::consts::OS,
47+
std::mem::size_of::<usize>() * 8,
48+
layouts.join(",\n ")
49+
);
50+
51+
let artifact_dir = target_dir().join("layout-artifacts");
52+
fs::create_dir_all(&artifact_dir).expect("create layout artifact directory");
53+
fs::write(artifact_dir.join("layout-bench.json"), &snapshot)
54+
.expect("write layout bench artifact");
55+
56+
println!("{snapshot}");
57+
}

scripts/bench-all.ps1

Lines changed: 16 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,16 @@
1+
$Version = if ($args.Count -gt 0) { $args[0] } else { "current" }
2+
$ResultDir = Join-Path "bench-results" $Version
3+
4+
New-Item -ItemType Directory -Force -Path $ResultDir | Out-Null
5+
6+
cargo test layout_snapshot --all-features -- --nocapture |
7+
Tee-Object -FilePath (Join-Path $ResultDir "layout-test.txt")
8+
9+
cargo bench --bench layout |
10+
Tee-Object -FilePath (Join-Path $ResultDir "layout-bench.txt")
11+
12+
cargo bench --bench comprehensive |
13+
Tee-Object -FilePath (Join-Path $ResultDir "comprehensive.txt")
14+
15+
cargo bench --bench simd --features simd |
16+
Tee-Object -FilePath (Join-Path $ResultDir "simd.txt")

scripts/bench-all.sh

Lines changed: 12 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,12 @@
1+
#!/usr/bin/env sh
2+
set -eu
3+
4+
VERSION="${1:-current}"
5+
RESULT_DIR="bench-results/${VERSION}"
6+
7+
mkdir -p "$RESULT_DIR"
8+
9+
cargo test layout_snapshot --all-features -- --nocapture | tee "$RESULT_DIR/layout-test.txt"
10+
cargo bench --bench layout | tee "$RESULT_DIR/layout-bench.txt"
11+
cargo bench --bench comprehensive | tee "$RESULT_DIR/comprehensive.txt"
12+
cargo bench --bench simd --features simd | tee "$RESULT_DIR/simd.txt"

tests/layout_snapshot.rs

Lines changed: 62 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,62 @@
1+
use cheetah_string::CheetahString;
2+
use std::env;
3+
use std::fs;
4+
use std::mem::{align_of, size_of};
5+
use std::path::PathBuf;
6+
7+
fn target_dir() -> PathBuf {
8+
env::var_os("CARGO_TARGET_DIR")
9+
.map(PathBuf::from)
10+
.unwrap_or_else(|| PathBuf::from("target"))
11+
}
12+
13+
fn layout_entry<T>(name: &str) -> String {
14+
format!(
15+
r#"{{"type":"{}","size":{},"align":{}}}"#,
16+
name,
17+
size_of::<T>(),
18+
align_of::<T>()
19+
)
20+
}
21+
22+
#[test]
23+
fn layout_snapshot() {
24+
let layouts = [
25+
layout_entry::<CheetahString>("CheetahString"),
26+
layout_entry::<Option<CheetahString>>("Option<CheetahString>"),
27+
layout_entry::<String>("String"),
28+
layout_entry::<Option<String>>("Option<String>"),
29+
layout_entry::<&str>("&str"),
30+
layout_entry::<Option<&str>>("Option<&str>"),
31+
layout_entry::<std::sync::Arc<str>>("Arc<str>"),
32+
layout_entry::<Option<std::sync::Arc<str>>>("Option<Arc<str>>"),
33+
];
34+
35+
let snapshot = format!(
36+
concat!(
37+
"{{\n",
38+
" \"crate\":\"cheetah-string\",\n",
39+
" \"profile\":\"test\",\n",
40+
" \"target_arch\":\"{}\",\n",
41+
" \"target_os\":\"{}\",\n",
42+
" \"pointer_width\":\"{}\",\n",
43+
" \"layouts\":[\n {}\n ]\n",
44+
"}}\n"
45+
),
46+
env::consts::ARCH,
47+
env::consts::OS,
48+
std::mem::size_of::<usize>() * 8,
49+
layouts.join(",\n ")
50+
);
51+
52+
let artifact_dir = target_dir().join("layout-artifacts");
53+
fs::create_dir_all(&artifact_dir).expect("create layout artifact directory");
54+
fs::write(artifact_dir.join("layout-snapshot.json"), &snapshot)
55+
.expect("write layout snapshot artifact");
56+
57+
println!("{snapshot}");
58+
59+
assert!(size_of::<CheetahString>() >= size_of::<usize>());
60+
assert!(align_of::<CheetahString>() >= align_of::<usize>());
61+
assert!(size_of::<Option<CheetahString>>() >= size_of::<CheetahString>());
62+
}

0 commit comments

Comments
 (0)