From 5936c1cef4d8aac668dfa7278ab8d4810af3e130 Mon Sep 17 00:00:00 2001 From: Carter Li Date: Thu, 27 Aug 2026 10:15:25 +0800 Subject: [PATCH] CI: adds benchmark job --- .github/workflows/benchmark-index.html | 405 ++++++++++++++++++++++ .github/workflows/build-benchmark.yml | 56 +++ .github/workflows/build-linux-hosts.yml | 32 +- .github/workflows/build-macos-hosts.yml | 32 +- .github/workflows/build-windows-hosts.yml | 32 +- .github/workflows/ci.yml | 11 + 6 files changed, 562 insertions(+), 6 deletions(-) create mode 100644 .github/workflows/benchmark-index.html create mode 100644 .github/workflows/build-benchmark.yml diff --git a/.github/workflows/benchmark-index.html b/.github/workflows/benchmark-index.html new file mode 100644 index 000000000..a2b9e309a --- /dev/null +++ b/.github/workflows/benchmark-index.html @@ -0,0 +1,405 @@ + + + + + + Fastfetch · Benchmark + + + + + +
+
+

Fastfetch Benchmark

+ +
+

Performance history grouped by CPU family. Each chart contains all modules and total process time for one operating system and architecture. Module curves are available from the legend and hidden by default.

+ +
+ +
+ + + diff --git a/.github/workflows/build-benchmark.yml b/.github/workflows/build-benchmark.yml new file mode 100644 index 000000000..827d81c39 --- /dev/null +++ b/.github/workflows/build-benchmark.yml @@ -0,0 +1,56 @@ +name: Reusable Benchmark + +on: + workflow_call: + +permissions: + contents: write + +jobs: + benchmark: + runs-on: ubuntu-latest + concurrency: + group: benchmark + cancel-in-progress: false + steps: + - name: checkout repository + uses: actions/checkout@3d3c42e5aac5ba805825da76410c181273ba90b1 # v7.0.1 + + - name: download benchmark data + uses: actions/download-artifact@3e5f45b2cfb9172054b4087a40e8e0b5a5461e7c # v8.0.1 + with: + pattern: benchmark-* + path: benchmarks + + - name: merge benchmark data + run: jq -s 'add' benchmarks/*/benchmark.json > benchmark.json + + - name: save benchmark dashboard + run: cp .github/benchmark-index.html "$RUNNER_TEMP/benchmark-index.html" + + - name: store benchmark result + uses: benchmark-action/github-action-benchmark@52576c92bccf6ac60c8223ec7eb2565637cae9ba # v1.22.1 + with: + name: Fastfetch + tool: customSmallerIsBetter + output-file-path: benchmark.json + github-token: ${{ secrets.GITHUB_TOKEN }} + ref: ${{ github.sha }} + auto-push: true + summary-always: true + fail-on-alert: true + benchmark-data-dir-path: dev/bench + + - name: publish benchmark dashboard + run: | + git fetch origin gh-pages + git switch --force-create gh-pages FETCH_HEAD + mkdir -p dev/bench + cp "$RUNNER_TEMP/benchmark-index.html" dev/bench/index.html + git config user.name github-action-benchmark + git config user.email github@users.noreply.github.com + git add dev/bench/index.html + if ! git diff --cached --quiet; then + git commit -m "Update benchmark dashboard" + git push origin gh-pages + fi diff --git a/.github/workflows/build-linux-hosts.yml b/.github/workflows/build-linux-hosts.yml index 612e7165f..19aec15b0 100644 --- a/.github/workflows/build-linux-hosts.yml +++ b/.github/workflows/build-linux-hosts.yml @@ -43,7 +43,7 @@ jobs: run: sudo add-apt-repository -y ppa:ubuntu-toolchain-r/test - name: install required packages - run: sudo apt-get update && sudo apt-get install -y gcc-13 libvulkan-dev libwayland-dev libxrandr-dev libxcb-randr0-dev libdconf-dev libdbus-1-dev libmagickcore-dev libsqlite3-dev librpm-dev libegl-dev libglx-dev ocl-icd-opencl-dev libpulse-dev libdrm-dev libelf-dev libddcutil-dev libefl-all-dev libunwind-dev liblua5.4-dev libvdpau-dev libva-dev rpm ninja-build + run: sudo apt-get update && sudo apt-get install -y gcc-13 jq libvulkan-dev libwayland-dev libxrandr-dev libxcb-randr0-dev libdconf-dev libdbus-1-dev libmagickcore-dev libsqlite3-dev librpm-dev libegl-dev libglx-dev ocl-icd-opencl-dev libpulse-dev libdrm-dev libelf-dev libddcutil-dev libefl-all-dev libunwind-dev liblua5.4-dev libvdpau-dev libva-dev rpm ninja-build - name: install linuxbrew packages run: | @@ -73,7 +73,29 @@ jobs: run: time ./fastfetch -c presets/ci.jsonc --stat false - name: run fastfetch --format json - run: time ./fastfetch -c presets/ci.jsonc --format json + run: | + { time -p ./fastfetch -c presets/ci.jsonc --format json > fastfetch.raw.json 2> fastfetch.error; } 2> fastfetch.time + sed -n '/^[[:space:]]*\[/,$p' fastfetch.raw.json > fastfetch.json + cat fastfetch.json + cat fastfetch.error >&2 + cat fastfetch.time >&2 + + - name: prepare benchmark data + run: | + real_seconds=$(awk '$1 == "real" { print $2 }' fastfetch.time) + jq -e 'type == "array"' fastfetch.json > /dev/null + jq --arg platform "linux" --arg arch "${{ inputs.arch }}" --argjson real_seconds "$real_seconds" ' + map(select(.stat | type == "number") | { + name: ("fastfetch " + $platform + " " + $arch + " module " + .type), + unit: "ms", + value: .stat + }) + [{ + name: ("fastfetch " + $platform + " " + $arch + " total process time"), + unit: "ms", + value: ($real_seconds * 1000) + }] + ' fastfetch.json > benchmark.json + cat benchmark.json - name: run flashfetch run: time ./flashfetch @@ -105,3 +127,9 @@ jobs: with: name: fastfetch-linux-${{ inputs.arch }} path: ./fastfetch-*.* + + - name: upload benchmark data + uses: actions/upload-artifact@043fb46d1a93c77aae656e7c1c64a875d1fc6a0a # v7.0.1 + with: + name: benchmark-linux-${{ inputs.arch }} + path: benchmark.json diff --git a/.github/workflows/build-macos-hosts.yml b/.github/workflows/build-macos-hosts.yml index 573165518..d805bf70d 100644 --- a/.github/workflows/build-macos-hosts.yml +++ b/.github/workflows/build-macos-hosts.yml @@ -29,7 +29,7 @@ jobs: - name: install required packages run: | HOMEBREW_NO_INSTALLED_DEPENDENTS_CHECK=1 brew update - HOMEBREW_NO_INSTALLED_DEPENDENTS_CHECK=1 brew install --overwrite vulkan-loader vulkan-headers molten-vk imagemagick chafa lua quickjs-ng + HOMEBREW_NO_INSTALLED_DEPENDENTS_CHECK=1 brew install --overwrite vulkan-loader vulkan-headers molten-vk imagemagick chafa lua quickjs-ng jq - name: configure project run: cmake -DSET_TWEAK=Off -DBUILD_TESTS=On . @@ -44,7 +44,29 @@ jobs: run: time ./fastfetch -c presets/ci.jsonc --structure-disabled vulkan:bluetooth:bluetoothradio --stat false - name: run fastfetch --format json - run: time ./fastfetch -c presets/ci.jsonc --structure-disabled vulkan:bluetooth:bluetoothradio --format json + run: | + { time -p ./fastfetch -c presets/ci.jsonc --structure-disabled vulkan:bluetooth:bluetoothradio --format json > fastfetch.raw.json 2> fastfetch.error; } 2> fastfetch.time + sed -n '/^[[:space:]]*\[/,$p' fastfetch.raw.json > fastfetch.json + cat fastfetch.json + cat fastfetch.error >&2 + cat fastfetch.time >&2 + + - name: prepare benchmark data + run: | + real_seconds=$(awk '$1 == "real" { print $2 }' fastfetch.time) + jq -e 'type == "array"' fastfetch.json > /dev/null + jq --arg platform "macos" --arg arch "${{ inputs.arch }}" --argjson real_seconds "$real_seconds" ' + map(select(.stat | type == "number") | { + name: ("fastfetch " + $platform + " " + $arch + " module " + .type), + unit: "ms", + value: .stat + }) + [{ + name: ("fastfetch " + $platform + " " + $arch + " total process time"), + unit: "ms", + value: ($real_seconds * 1000) + }] + ' fastfetch.json > benchmark.json + cat benchmark.json - name: run flashfetch run: time ./flashfetch @@ -60,3 +82,9 @@ jobs: with: name: fastfetch-macos-${{ inputs.arch }} path: ./fastfetch-*.* + + - name: upload benchmark data + uses: actions/upload-artifact@043fb46d1a93c77aae656e7c1c64a875d1fc6a0a # v7.0.1 + with: + name: benchmark-macos-${{ inputs.arch }} + path: benchmark.json diff --git a/.github/workflows/build-windows-hosts.yml b/.github/workflows/build-windows-hosts.yml index 2ef399f97..2518c25d6 100644 --- a/.github/workflows/build-windows-hosts.yml +++ b/.github/workflows/build-windows-hosts.yml @@ -49,7 +49,7 @@ jobs: with: msystem: ${{ inputs.msystem }} update: true - install: git mingw-w64-clang-${{ inputs.msys-arch }}-7zip mingw-w64-clang-${{ inputs.msys-arch }}-cmake mingw-w64-clang-${{ inputs.msys-arch }}-clang mingw-w64-clang-${{ inputs.msys-arch }}-vulkan-loader mingw-w64-clang-${{ inputs.msys-arch }}-vulkan-headers mingw-w64-clang-${{ inputs.msys-arch }}-opencl-icd mingw-w64-clang-${{ inputs.msys-arch }}-opencl-headers mingw-w64-clang-${{ inputs.msys-arch }}-cppwinrt mingw-w64-clang-${{ inputs.msys-arch }}-imagemagick mingw-w64-clang-${{ inputs.msys-arch }}-chafa mingw-w64-clang-${{ inputs.msys-arch }}-lua mingw-w64-clang-${{ inputs.msys-arch }}-quickjs-ng mingw-w64-clang-${{ inputs.msys-arch }}-directx-headers + install: git mingw-w64-clang-${{ inputs.msys-arch }}-7zip mingw-w64-clang-${{ inputs.msys-arch }}-cmake mingw-w64-clang-${{ inputs.msys-arch }}-clang mingw-w64-clang-${{ inputs.msys-arch }}-jq mingw-w64-clang-${{ inputs.msys-arch }}-vulkan-loader mingw-w64-clang-${{ inputs.msys-arch }}-vulkan-headers mingw-w64-clang-${{ inputs.msys-arch }}-opencl-icd mingw-w64-clang-${{ inputs.msys-arch }}-opencl-headers mingw-w64-clang-${{ inputs.msys-arch }}-cppwinrt mingw-w64-clang-${{ inputs.msys-arch }}-imagemagick mingw-w64-clang-${{ inputs.msys-arch }}-chafa mingw-w64-clang-${{ inputs.msys-arch }}-lua mingw-w64-clang-${{ inputs.msys-arch }}-quickjs-ng mingw-w64-clang-${{ inputs.msys-arch }}-directx-headers - name: print msys version run: uname -a @@ -70,7 +70,29 @@ jobs: run: time ./fastfetch -c presets/ci.jsonc --stat false - name: run fastfetch --format json - run: time ./fastfetch -c presets/ci.jsonc --format json + run: | + { time -p ./fastfetch -c presets/ci.jsonc --format json > fastfetch.raw.json 2> fastfetch.error; } 2> fastfetch.time + sed -n '/^[[:space:]]*\[/,$p' fastfetch.raw.json > fastfetch.json + cat fastfetch.json + cat fastfetch.error >&2 + cat fastfetch.time >&2 + + - name: prepare benchmark data + run: | + real_seconds=$(awk '$1 == "real" { print $2 }' fastfetch.time) + jq -e 'type == "array"' fastfetch.json > /dev/null + jq --arg platform "windows" --arg arch "${{ inputs.arch }}" --argjson real_seconds "$real_seconds" ' + map(select(.stat | type == "number") | { + name: ("fastfetch " + $platform + " " + $arch + " module " + .type), + unit: "ms", + value: .stat + }) + [{ + name: ("fastfetch " + $platform + " " + $arch + " total process time"), + unit: "ms", + value: ($real_seconds * 1000) + }] + ' fastfetch.json > benchmark.json + cat benchmark.json - name: run flashfetch run: time ./flashfetch @@ -116,3 +138,9 @@ jobs: name: fastfetch-windows-${{ inputs.arch }} path: ./fastfetch-windows-${{ inputs.arch }}.* overwrite: true + + - name: upload benchmark data + uses: actions/upload-artifact@043fb46d1a93c77aae656e7c1c64a875d1fc6a0a # v7.0.1 + with: + name: benchmark-windows-${{ inputs.arch }} + path: benchmark.json diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml index 0081e62d8..8f63fdc04 100644 --- a/.github/workflows/ci.yml +++ b/.github/workflows/ci.yml @@ -176,6 +176,17 @@ jobs: secrets: SIGNPATH_API_TOKEN: ${{ secrets.SIGNPATH_API_TOKEN }} + benchmark: + if: github.event_name == 'push' && github.ref == 'refs/heads/dev' && github.repository == 'fastfetch-cli/fastfetch' + name: Benchmark + needs: + - linux-hosts + - macos-hosts + - windows-hosts + permissions: + contents: write + uses: ./.github/workflows/build-benchmark.yml + release: if: github.event_name == 'push' && github.ref == 'refs/heads/master' && github.repository == 'fastfetch-cli/fastfetch' name: Release