feat(benchmark): add performance report generation and clean output d… #75
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| name: CI | |
| on: | |
| pull_request: | |
| push: | |
| workflow_dispatch: | |
| permissions: | |
| contents: read | |
| jobs: | |
| build: | |
| uses: ./.github/workflows/build-matrix.yml | |
| with: | |
| build_type: Debug | |
| run_tests: true | |
| clang-format-report: | |
| name: clang-format report | |
| runs-on: ubuntu-latest | |
| steps: | |
| - name: Checkout | |
| uses: actions/checkout@v4 | |
| - name: Setup Homebrew | |
| uses: Homebrew/actions/setup-homebrew@main | |
| - name: Install latest clang-format and gersemi (Linuxbrew) | |
| shell: bash | |
| run: | | |
| set -euo pipefail | |
| brew update | |
| brew install clang-format gersemi | |
| brew upgrade clang-format gersemi | |
| echo "$(brew --prefix clang-format)/bin" >> "$GITHUB_PATH" | |
| echo "$(brew --prefix)/bin" >> "$GITHUB_PATH" | |
| clang-format --version | |
| gersemi --version | |
| - name: Check formatting | |
| shell: bash | |
| run: | | |
| set -euo pipefail | |
| mapfile -t files < <(git ls-files \ | |
| '*.c' '*.cc' '*.cpp' '*.cxx' '*.h' '*.hpp' '*.hxx' '*.inl') | |
| if [ "${#files[@]}" -eq 0 ]; then | |
| echo "No format-managed files found." | |
| exit 0 | |
| fi | |
| clang-format --dry-run --Werror "${files[@]}" | |
| - name: Check CMake formatting | |
| shell: bash | |
| run: | | |
| set -euo pipefail | |
| mapfile -t cmake_files < <(git ls-files \ | |
| 'CMakeLists.txt' '*.cmake') | |
| if [ "${#cmake_files[@]}" -eq 0 ]; then | |
| echo "No CMake files found." | |
| exit 0 | |
| fi | |
| gersemi --check "${cmake_files[@]}" | |
| sanitizer: | |
| name: Sanitizer ${{ matrix.name }} | |
| runs-on: ubuntu-latest | |
| strategy: | |
| fail-fast: false | |
| matrix: | |
| include: | |
| - name: ASAN+UBSAN+LSAN | |
| build_dir: build/asan | |
| c_flags: -fsanitize=address,undefined,leak -fno-omit-frame-pointer | |
| cxx_flags: -fsanitize=address,undefined,leak -fno-omit-frame-pointer | |
| exe_linker_flags: -fsanitize=address,undefined,leak | |
| shared_linker_flags: -fsanitize=address,undefined,leak | |
| requires_rtsan_probe: false | |
| - name: TSAN | |
| build_dir: build/tsan | |
| c_flags: -fsanitize=thread -fno-omit-frame-pointer | |
| cxx_flags: -fsanitize=thread -fno-omit-frame-pointer | |
| exe_linker_flags: -fsanitize=thread | |
| shared_linker_flags: -fsanitize=thread | |
| requires_rtsan_probe: false | |
| - name: RTSAN | |
| build_dir: build/rtsan | |
| c_flags: -fsanitize=realtime -fno-omit-frame-pointer | |
| cxx_flags: -fsanitize=realtime -fno-omit-frame-pointer | |
| exe_linker_flags: -fsanitize=realtime | |
| shared_linker_flags: -fsanitize=realtime | |
| requires_rtsan_probe: true | |
| steps: | |
| - name: Checkout | |
| uses: actions/checkout@v4 | |
| - name: Setup Homebrew | |
| uses: Homebrew/actions/setup-homebrew@main | |
| - name: Install Homebrew packages | |
| shell: bash | |
| run: | | |
| set -euo pipefail | |
| brew update | |
| brew install llvm | |
| echo "$(brew --prefix llvm)/bin" >> "$GITHUB_PATH" | |
| cmake --version | |
| clang --version | |
| - name: Probe realtime sanitizer support | |
| if: matrix.requires_rtsan_probe | |
| id: rtsan-probe | |
| shell: bash | |
| run: | | |
| set -euo pipefail | |
| cat > /tmp/rtsan_probe.cpp << 'EOF' | |
| int main() { return 0; } | |
| EOF | |
| if clang++ -fsanitize=realtime /tmp/rtsan_probe.cpp -o /tmp/rtsan_probe >/dev/null 2>&1; then | |
| echo "supported=true" >> "$GITHUB_OUTPUT" | |
| else | |
| echo "supported=false" >> "$GITHUB_OUTPUT" | |
| fi | |
| - name: Setup sccache | |
| uses: mozilla-actions/sccache-action@v0.0.10 | |
| - name: Configure | |
| if: ${{ !matrix.requires_rtsan_probe || steps.rtsan-probe.outputs.supported == 'true' }} | |
| shell: bash | |
| run: | | |
| set -euo pipefail | |
| cmake -B ${{ matrix.build_dir }} -G Ninja \ | |
| -DCMAKE_BUILD_TYPE=RelWithDebInfo \ | |
| -DCMAKE_C_COMPILER=clang \ | |
| -DCMAKE_CXX_COMPILER=clang++ \ | |
| -DCMAKE_C_COMPILER_LAUNCHER=sccache \ | |
| -DCMAKE_CXX_COMPILER_LAUNCHER=sccache \ | |
| -DCMAKE_C_FLAGS="${{ matrix.c_flags }}" \ | |
| -DCMAKE_CXX_FLAGS="${{ matrix.cxx_flags }}" \ | |
| -DCMAKE_EXE_LINKER_FLAGS="${{ matrix.exe_linker_flags }}" \ | |
| -DCMAKE_SHARED_LINKER_FLAGS="${{ matrix.shared_linker_flags }}" | |
| - name: Build | |
| if: ${{ !matrix.requires_rtsan_probe || steps.rtsan-probe.outputs.supported == 'true' }} | |
| run: cmake --build ${{ matrix.build_dir }} | |
| - name: Test | |
| if: ${{ !matrix.requires_rtsan_probe || steps.rtsan-probe.outputs.supported == 'true' }} | |
| run: ctest --test-dir ${{ matrix.build_dir }} --output-on-failure | |
| - name: RTSAN unavailable note | |
| if: ${{ matrix.requires_rtsan_probe && steps.rtsan-probe.outputs.supported != 'true' }} | |
| run: | | |
| echo "RTSAN is not supported by this LLVM toolchain; skipping job payload." | |
| benchmark-linux-clang-release: | |
| name: Benchmarks & Profiling | |
| runs-on: ubuntu-latest | |
| steps: | |
| - name: Checkout | |
| uses: actions/checkout@v4 | |
| - name: Setup Homebrew | |
| uses: Homebrew/actions/setup-homebrew@main | |
| - name: Install LLVM and Ninja (Linuxbrew) | |
| shell: bash | |
| run: | | |
| set -euo pipefail | |
| brew update | |
| brew install llvm ninja | |
| echo "$(brew --prefix llvm)/bin" >> "$GITHUB_PATH" | |
| cmake --version | |
| clang --version | |
| - name: Ensure perf is available | |
| shell: bash | |
| run: | | |
| set -euo pipefail | |
| if ! command -v perf >/dev/null 2>&1; then | |
| sudo apt-get update | |
| sudo apt-get install -y linux-tools-generic | |
| fi | |
| perf --version | |
| - name: Allow perf profiling (relax perf_event_paranoid) | |
| shell: bash | |
| run: | | |
| set -euo pipefail | |
| sudo sysctl -w kernel.perf_event_paranoid=1 | |
| - name: Cache CMake deps | |
| uses: actions/cache@v4 | |
| with: | |
| path: | | |
| build/benchmark-release/_deps | |
| key: >- | |
| benchmark-linux-clang-release-${{ hashFiles('CMakeLists.txt', 'cmake/**/*.cmake', 'src/*_bench.cpp') }} | |
| - name: Configure (Release, Clang) | |
| shell: bash | |
| run: | | |
| set -euo pipefail | |
| cmake -B build/benchmark-release -G Ninja \ | |
| -DCMAKE_BUILD_TYPE=Release \ | |
| -DCMAKE_C_COMPILER=clang \ | |
| -DCMAKE_CXX_COMPILER=clang++ \ | |
| -DENABLE_BENCHMARK_TESTS=ON | |
| - name: Build benchmarks | |
| shell: bash | |
| run: | | |
| set -euo pipefail | |
| cmake --build build/benchmark-release | |
| - name: Run benchmarks | |
| shell: bash | |
| run: | | |
| set -euo pipefail | |
| ctest --test-dir build/benchmark-release --label-regex benchmark --output-on-failure | |
| - name: Upload benchmark and profiling artifacts | |
| uses: actions/upload-artifact@v4 | |
| with: | |
| name: benchmark-linux-clang-release-results | |
| path: build/benchmark-release/benchmarks/** | |
| if-no-files-found: error | |
| - name: Clean benchmark output directory | |
| shell: bash | |
| run: rm -rf build/benchmark-release/benchmarks |