Skip to content
Closed
Show file tree
Hide file tree
Changes from all commits
Commits
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
165 changes: 165 additions & 0 deletions .github/workflows/benchmark.yml
Original file line number Diff line number Diff line change
@@ -0,0 +1,165 @@
name: Benchmarks

on:
push:
branches:
- master
pull_request:
branches:
- master

# Sets permissions of the GITHUB_TOKEN to allow deployment to GitHub Pages
permissions:
contents: read
pages: write
id-token: write

# Allow only one concurrent deployment, skipping runs queued between the run in-progress and latest queued.
concurrency:
group: "benchmarks"
cancel-in-progress: false

jobs:
build-and-benchmark:
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v5
- name: Setup Pages
uses: actions/configure-pages@v3
- name: Setup necessary dotnet SDKs
uses: actions/setup-dotnet@v4
with:
global-json-file: global.json
dotnet-version: |
8.x
9.x
- name: Run benchmarks
run: |
chmod +x ./build.sh
./build.sh Benchmarks
env:
CI: true
CONFIGURATION: Release
- name: Combine benchmark results
run: |
# Run the F# script to combine multiple JSON files into one
if [ -d "BenchmarkDotNet.Artifacts/results" ]; then
echo "Combining benchmark results..."
dotnet fsi combine-benchmarks.fsx -d "BenchmarkDotNet.Artifacts/results" -o "IcedTasks-Combined-Benchmarks" -p "*-report-full-compressed.json"

echo "=== Combined benchmark file ==="
ls -la BenchmarkDotNet.Artifacts/results/IcedTasks-Combined-Benchmarks.json || echo "Combined file not found"
else
echo "No benchmark results directory found"
fi

- name: Store benchmark result
uses: benchmark-action/github-action-benchmark@v1
with:
name: IcedTasks Benchmark
tool: 'benchmarkdotnet'
output-file-path: 'BenchmarkDotNet.Artifacts/results/IcedTasks-Combined-Benchmarks.json'
github-token: ${{ secrets.GITHUB_TOKEN }}
auto-push: false
# This is the key parameter - tells the action where to write results instead of using gh-pages
external-data-json-path: 'benchmark-data/data.json'
# Store data in a different location that we'll use for Pages deployment
benchmark-data-dir-path: 'benchmark-data'
# Show alert with commit comment on detecting possible performance regression
alert-threshold: '200%'
comment-on-alert: true
fail-on-alert: false
alert-comment-cc-users: '@TheAngryByrd'

- name: Debug - Show benchmark action output
run: |
echo "=== Benchmark action output ==="
ls -la benchmark-data/ || echo "benchmark-data directory not found"
find . -name "*.html" -o -name "*.js" -o -name "*.json" | grep -E "(benchmark|chart)" || echo "No benchmark web files found"

- name: Download latest GitHub Pages artifact
run: |
# Get the latest successful run ID from the docs workflow
RUN_ID=$(gh run list --workflow="Deploy Docs" --status=success --limit=1 --json databaseId --jq '.[0].databaseId')

if [ ! -z "$RUN_ID" ] && [ "$RUN_ID" != "null" ]; then
echo "Found docs workflow run: $RUN_ID"
# Download the github-pages artifact from that run
gh run download $RUN_ID --name github-pages --dir existing-pages
echo "artifact_downloaded=true" >> $GITHUB_ENV
else
echo "No successful docs workflow run found"
echo "artifact_downloaded=false" >> $GITHUB_ENV
fi
env:
GH_TOKEN: ${{ secrets.GITHUB_TOKEN }}
continue-on-error: true

- name: Extract existing pages and add benchmarks
run: |
# Create a combined directory for deployment
mkdir -p combined-site

# If we successfully downloaded existing pages, extract them
if [ "$artifact_downloaded" = "true" ] && [ -d "existing-pages" ]; then
echo "Extracting existing pages artifact..."
# GitHub Pages artifacts are typically tar.gz files
if [ -f "existing-pages/artifact.tar.gz" ]; then
cd existing-pages
tar -xzf artifact.tar.gz
cd ..
# Copy existing pages to combined site (skip the tar file itself)
find existing-pages -type f ! -name "*.tar.gz" -exec cp {} combined-site/ \;
find existing-pages -type d ! -name "existing-pages" -exec mkdir -p combined-site/{} \; 2>/dev/null || true
elif [ -f "existing-pages/artifact.tar" ]; then
cd existing-pages
tar -xf artifact.tar
cd ..
find existing-pages -type f ! -name "*.tar" -exec cp {} combined-site/ \;
else
# Just copy all files if no tar found
cp -r existing-pages/* combined-site/ 2>/dev/null || true
fi
echo "Existing pages extracted successfully"
else
echo "No existing pages found, creating basic site structure..."
# Create a basic index if no existing pages
echo '<html><head><title>IcedTasks</title></head><body><h1>IcedTasks</h1><p><a href="benchmarks/">View Benchmarks</a></p></body></html>' > combined-site/index.html
fi

# Copy benchmark results to benchmarks subdirectory
mkdir -p combined-site/benchmarks
if [ -d "benchmark-data" ]; then
cp -r benchmark-data/* combined-site/benchmarks/
echo "Benchmark data copied to combined-site/benchmarks/"
else
echo "No benchmark data found in benchmark-data directory"
# List what directories we do have for debugging
echo "Available directories:"
ls -la . | grep "^d" || true
fi

# List what we have in combined-site for debugging
echo "Contents of combined-site:"
ls -la combined-site/ || true
echo "Contents of combined-site/benchmarks:"
ls -la combined-site/benchmarks/ || true

- name: Upload combined pages artifact
uses: actions/upload-pages-artifact@v3
with:
path: combined-site

# Deployment job
deploy:
# Only deploy on pushes to master branch, not on pull requests
if: github.event_name == 'push' && github.ref == 'refs/heads/master'
environment:
name: github-pages
url: ${{ steps.deployment.outputs.page_url }}
runs-on: ubuntu-latest
needs: build-and-benchmark
steps:
- name: Deploy to GitHub Pages
id: deployment
uses: actions/deploy-pages@v4
2 changes: 2 additions & 0 deletions .gitignore
Original file line number Diff line number Diff line change
Expand Up @@ -276,3 +276,5 @@ temp/
.fsdocs
runtime-scripts/
docs/

BenchmarkDotNet.Artifacts/
2 changes: 1 addition & 1 deletion Directory.Packages.props
Original file line number Diff line number Diff line change
Expand Up @@ -16,7 +16,7 @@
<PackageVersion Include="Microsoft.Bcl.AsyncInterfaces" Version="6.0.0"/>

<!-- Benchmarks -->
<PackageVersion Include="BenchmarkDotNet" Version="0.13.9"/>
<PackageVersion Include="BenchmarkDotNet" Version="0.15.3"/>
<PackageVersion Include="Ply" Version="0.3.1"/>

<!-- Test -->
Expand Down
30 changes: 30 additions & 0 deletions build/build.fs
Original file line number Diff line number Diff line change
Expand Up @@ -92,6 +92,12 @@ let releaseBranch = "master"
let readme = "README.md"
let changelogFile = "CHANGELOG.md"

let fsharpBenchmarksProj =
rootDirectory
</> "benchmarks"
</> "FSharpBenchmarks"
</> "benchmarks.fsproj"

let tagFromVersionNumber versionNumber = sprintf "v%s" versionNumber

let READMElink = Uri(Uri(gitHubRepoUrl), $"blob/{releaseBranch}/{readme}")
Expand Down Expand Up @@ -620,6 +626,28 @@ let watchDocs ctx =
DocsTool.watch (string configuration)


let benchmarks _ =
let args = [
"--project"
fsharpBenchmarksProj
"-c"
"Release"
"-f"
"net8.0"
"--"
"--exporters"
"json"
"--filter"
"*"
"--runtimes"
"net9.0"
"net8.0"
"--job=short"
]

dotnet.run id (String.concat " " args)
|> failOnBadExitAndPrint

let initTargets () =
BuildServer.install [ GitHubActions.Installer ]

Expand Down Expand Up @@ -662,6 +690,8 @@ let initTargets () =
Target.create "CleanDocsCache" cleanDocsCache
Target.create "BuildDocs" buildDocs
Target.create "WatchDocs" watchDocs
Target.create "Benchmarks" benchmarks


//-----------------------------------------------------------------------------
// Target Dependencies
Expand Down
Loading
Loading