Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
36 commits
Select commit Hold shift + click to select a range
742f699
finish hash and histogram detector
al8n Apr 15, 2026
6951030
finish hash and histogram detector
al8n Apr 15, 2026
621e8e6
finish threshold detector
al8n Apr 15, 2026
c228147
finish content detector
al8n Apr 15, 2026
bad9dbb
add threshold and content benchmarks
al8n Apr 15, 2026
259b858
content: van-Herk O(n) dilate + refactor cleanups
al8n Apr 15, 2026
7ac4a74
simd optimization
al8n Apr 16, 2026
6fcb2fb
optimize threshold detector
al8n Apr 16, 2026
36ec97c
fix fmt
al8n Apr 16, 2026
5985518
optimize adaptive detector code
al8n Apr 16, 2026
fd6049b
update benchmark code
al8n Apr 16, 2026
62f9fe2
fix no-std build
al8n Apr 16, 2026
1db143b
fix doc warnings
al8n Apr 16, 2026
4c0f582
fix doc warnings
al8n Apr 16, 2026
2c2756e
fix fmt
al8n Apr 16, 2026
a64d1ff
cleanup
al8n Apr 17, 2026
5f2b19b
cleanup ci
al8n Apr 17, 2026
30d3c32
update README
al8n Apr 17, 2026
101b087
update README
al8n Apr 17, 2026
b7cbe54
update README
al8n Apr 17, 2026
b66f9a9
update README
al8n Apr 17, 2026
757cf25
update
al8n Apr 17, 2026
839939f
update
al8n Apr 17, 2026
d60436d
Update src/content/arch.rs
al8n Apr 17, 2026
2e6babb
update
al8n Apr 17, 2026
7194180
update
al8n Apr 17, 2026
ea03711
update
al8n Apr 17, 2026
eb3d570
update
al8n Apr 17, 2026
a6af3ae
update
al8n Apr 17, 2026
55b3420
update
al8n Apr 17, 2026
761956d
update
al8n Apr 17, 2026
1787e4d
update
al8n Apr 17, 2026
24dc686
update
al8n Apr 17, 2026
c0223ff
update
al8n Apr 17, 2026
be24f1e
update
al8n Apr 17, 2026
2f1fc46
update
al8n Apr 17, 2026
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
267 changes: 267 additions & 0 deletions .github/workflows/benchmark.yml
Original file line number Diff line number Diff line change
@@ -0,0 +1,267 @@
name: Benchmarks

on:
push:
branches:
- main
paths:
- 'benches/**'
- 'src/**'
- 'Cargo.toml'
- 'Cargo.lock'
- '.github/workflows/benchmark.yml'
pull_request:
paths:
- 'benches/**'
- 'src/**'
- 'Cargo.toml'
- 'Cargo.lock'
- '.github/workflows/benchmark.yml'
workflow_dispatch:

env:
CARGO_TERM_COLOR: always
RUST_BACKTRACE: 1

jobs:
benchmark:
name: ${{ matrix.label }}
strategy:
fail-fast: false
matrix:
include:
# aarch64 — exercises the NEON SIMD backend (vld3q_u8 deinterleave,
# vabdq_u8 / vpaddlq mean-abs-diff, NEON Sobel).
- os: macos-latest
arch: aarch64
tier: neon
rustflags: ''
label: macos-aarch64-neon

# x86_64 default: the runtime dispatcher (`is_x86_feature_detected!`)
# picks AVX2 on modern GH runners, falls back to SSSE3 otherwise.
# This exercises the x86 dispatch code path as shipped.
- os: ubuntu-latest
arch: x86_64
tier: default
rustflags: ''
label: ubuntu-x86_64-default

# x86_64 with `-C target-cpu=native`: lets LLVM auto-vectorize the
# non-SIMD scalar code (histogram accumulate, phash DCT, adaptive
# rolling sum, etc.) with the full feature set of the runner's CPU.
# Complements the default tier to show the ceiling of scalar wins.
- os: ubuntu-latest
arch: x86_64
tier: native
rustflags: '-C target-cpu=native'
label: ubuntu-x86_64-native

# x86_64 with SSSE3 forced on at compile time and AVX/AVX2 off:
# exercises the SSSE3 dispatch path even when the runner CPU
# supports AVX2. We gate on compile-time target_feature in
# `content/arch.rs` only in the `not(feature = "std")` branch; with
# std the dispatcher uses `is_x86_feature_detected!`, so this tier
# primarily guards that the SSSE3 module *compiles* without AVX2.
- os: ubuntu-latest
arch: x86_64
tier: ssse3-only
rustflags: '-C target-feature=+ssse3,-avx,-avx2,-fma'
label: ubuntu-x86_64-ssse3-only

# Windows x86_64 — same dispatcher as Linux but validates the MSVC
# toolchain handles the intrinsics-heavy modules.
- os: windows-latest
arch: x86_64
tier: default
rustflags: ''
label: windows-x86_64-default

runs-on: ${{ matrix.os }}
env:
RUSTFLAGS: ${{ matrix.rustflags }}
steps:
- uses: actions/checkout@v6

- name: Install Rust
run: rustup update stable --no-self-update && rustup default stable

- name: Print CPU info (Linux)
if: runner.os == 'Linux'
shell: bash
run: |
echo "=== /proc/cpuinfo (first flags line) ==="
grep -m1 '^flags' /proc/cpuinfo || true
echo "=== lscpu ==="
lscpu || true

- name: Print CPU info (macOS)
if: runner.os == 'macOS'
shell: bash
run: |
echo "=== sysctl machdep.cpu ==="
sysctl machdep.cpu || true
echo "=== uname -m ==="
uname -m

- name: Print CPU info (Windows)
if: runner.os == 'Windows'
shell: pwsh
run: |
Get-CimInstance Win32_Processor | Select-Object Name, Manufacturer, NumberOfCores, NumberOfLogicalProcessors | Format-List

- name: Cache cargo build and registry
uses: actions/cache@v5
with:
path: |
~/.cargo/registry
~/.cargo/git
target
key: ${{ runner.os }}-bench-${{ matrix.tier }}-${{ hashFiles('**/Cargo.lock') }}
restore-keys: |
${{ runner.os }}-bench-${{ matrix.tier }}-
${{ runner.os }}-bench-

- name: Run benchmarks - histogram
shell: bash
run: cargo bench --bench histogram -- --output-format bencher | tee benchmark-histogram-${{ matrix.label }}.txt
continue-on-error: true

- name: Run benchmarks - phash
shell: bash
run: cargo bench --bench phash -- --output-format bencher | tee benchmark-phash-${{ matrix.label }}.txt
continue-on-error: true

- name: Run benchmarks - threshold
shell: bash
run: cargo bench --bench threshold -- --output-format bencher | tee benchmark-threshold-${{ matrix.label }}.txt
continue-on-error: true

- name: Run benchmarks - content
shell: bash
run: cargo bench --bench content -- --output-format bencher | tee benchmark-content-${{ matrix.label }}.txt
continue-on-error: true

- name: Run benchmarks - adaptive
shell: bash
run: cargo bench --bench adaptive -- --output-format bencher | tee benchmark-adaptive-${{ matrix.label }}.txt
continue-on-error: true

- name: Collect benchmark summary
shell: bash
run: |
summary="benchmark-summary-${{ matrix.label }}.md"
echo "## Benchmark Results for ${{ matrix.label }}" > "$summary"
echo "" >> "$summary"
echo "### System Information" >> "$summary"
echo "- OS: ${{ matrix.os }}" >> "$summary"
echo "- Arch: ${{ matrix.arch }}" >> "$summary"
echo "- SIMD tier: ${{ matrix.tier }}" >> "$summary"
echo "- Runner: ${{ runner.name }}" >> "$summary"
echo "- Runner arch (GH): ${{ runner.arch }}" >> "$summary"
echo "- RUSTFLAGS: \`${{ matrix.rustflags }}\`" >> "$summary"
echo "- Date: $(date -u +"%Y-%m-%d %H:%M:%S UTC")" >> "$summary"
echo "" >> "$summary"

for bench in histogram phash threshold content adaptive; do
file="benchmark-${bench}-${{ matrix.label }}.txt"
if [ -f "$file" ]; then
echo "### ${bench}" >> "$summary"
echo "" >> "$summary"
echo "\`\`\`" >> "$summary"
grep "^test " "$file" >> "$summary" || echo "No results" >> "$summary"
echo "\`\`\`" >> "$summary"
echo "" >> "$summary"
fi
done

cat "$summary"

- name: Create benchmark archive
shell: bash
run: |
mkdir -p benchmark-results
mv benchmark-*.txt benchmark-results/ 2>/dev/null || true
mv benchmark-summary-${{ matrix.label }}.md benchmark-results/ 2>/dev/null || true
if [ -d "target/criterion" ]; then
cp -r target/criterion benchmark-results/criterion-${{ matrix.label }} || true
fi

- name: Upload benchmark results
uses: actions/upload-artifact@v7
with:
name: benchmark-results-${{ matrix.label }}
path: benchmark-results/
retention-days: 90

- name: Upload Criterion detailed results
uses: actions/upload-artifact@v7
if: always()
with:
name: criterion-detailed-${{ matrix.label }}
path: target/criterion/
retention-days: 90
continue-on-error: true

# Aggregate results from all platforms and SIMD tiers.
aggregate-results:
name: Aggregate benchmark results
needs: benchmark
runs-on: ubuntu-latest
if: always()
steps:
- name: Download all benchmark results
uses: actions/download-artifact@v6
with:
path: all-results

- name: Create combined summary
shell: bash
run: |
echo "# Benchmark Results Summary" > BENCHMARK_SUMMARY.md
echo "" >> BENCHMARK_SUMMARY.md
echo "Date: $(date -u +"%Y-%m-%d %H:%M:%S UTC")" >> BENCHMARK_SUMMARY.md
echo "" >> BENCHMARK_SUMMARY.md

for os_dir in all-results/benchmark-results-*/; do
if [ -d "$os_dir" ]; then
for summary in "$os_dir"benchmark-summary-*.md; do
if [ -f "$summary" ]; then
echo "" >> BENCHMARK_SUMMARY.md
cat "$summary" >> BENCHMARK_SUMMARY.md
echo "" >> BENCHMARK_SUMMARY.md
echo "---" >> BENCHMARK_SUMMARY.md
fi
done
fi
done

cat BENCHMARK_SUMMARY.md

- name: Upload combined results
uses: actions/upload-artifact@v7
with:
name: benchmark-results-combined
path: |
BENCHMARK_SUMMARY.md
all-results/
retention-days: 90

- name: Comment PR with benchmark results
if: github.event_name == 'pull_request'
uses: actions/github-script@v9
with:
github-token: ${{ secrets.GITHUB_TOKEN }}
script: |
const fs = require('fs');
const summary = fs.readFileSync('BENCHMARK_SUMMARY.md', 'utf8');

const comment = `## Benchmark Results\n\n${summary}\n\n<details>\n<summary>View detailed results</summary>\n\nDetailed Criterion results have been uploaded as artifacts. Download them from the workflow run to view charts and detailed statistics.\n\n</details>`;

github.rest.issues.createComment({
issue_number: context.issue.number,
owner: context.repo.owner,
repo: context.repo.repo,
body: comment
});
continue-on-error: true
Loading
Loading