serialbench 0.2.0 → 0.3.1

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (54) hide show
  1. checksums.yaml +4 -4
  2. data/.github/scripts/push-to-data.sh +65 -0
  3. data/.github/workflows/benchmark.yml +106 -160
  4. data/.github/workflows/release.yml +68 -13
  5. data/Gemfile +1 -1
  6. data/config/benchmarks/full-json.yml +25 -0
  7. data/config/benchmarks/full-toml.yml +25 -0
  8. data/config/benchmarks/full-xml.yml +26 -0
  9. data/config/benchmarks/full-yaml.yml +25 -0
  10. data/config/benchmarks/full.yml +9 -4
  11. data/lib/serialbench/benchmark_runner.rb +20 -23
  12. data/lib/serialbench/cli/benchmark_cli.rb +1 -1
  13. data/lib/serialbench/cli.rb +1 -8
  14. data/lib/serialbench/models/benchmark_result.rb +2 -0
  15. data/lib/serialbench/serializers/base_serializer.rb +14 -2
  16. data/lib/serialbench/serializers/xml/base_xml_serializer.rb +6 -10
  17. data/lib/serialbench/serializers/xml/leptris_serializer.rb +15 -8
  18. data/lib/serialbench/serializers/xml/nokogiri_serializer.rb +2 -7
  19. data/lib/serialbench/serializers/xml/oga_serializer.rb +4 -0
  20. data/lib/serialbench/version.rb +1 -1
  21. data/lib/serialbench.rb +1 -1
  22. metadata +8 -38
  23. data/lib/serialbench/templates/assets/css/benchmark_report.css +0 -535
  24. data/lib/serialbench/templates/assets/css/format_based.css +0 -474
  25. data/lib/serialbench/templates/assets/css/themes.css +0 -589
  26. data/lib/serialbench/templates/assets/js/chart_helpers.js +0 -411
  27. data/lib/serialbench/templates/assets/js/dashboard.js +0 -795
  28. data/lib/serialbench/templates/assets/js/navigation.js +0 -142
  29. data/lib/serialbench/templates/base.liquid +0 -49
  30. data/lib/serialbench/templates/format_based.liquid +0 -507
  31. data/lib/serialbench/templates/partials/chart_section.liquid +0 -4
  32. data/site/.gitignore +0 -5
  33. data/site/README.md +0 -32
  34. data/site/astro.config.mjs +0 -12
  35. data/site/package-lock.json +0 -6160
  36. data/site/package.json +0 -22
  37. data/site/public/favicon.svg +0 -4
  38. data/site/scripts/gen-sample-data.mjs +0 -154
  39. data/site/src/components/AvailabilityMatrix.astro +0 -61
  40. data/site/src/components/CalibratedLeaderboard.vue +0 -134
  41. data/site/src/components/CitationBox.vue +0 -50
  42. data/site/src/components/DashboardConsole.vue +0 -193
  43. data/site/src/components/FeaturesTable.astro +0 -97
  44. data/site/src/components/MemoryPanel.vue +0 -44
  45. data/site/src/components/OpsChart.vue +0 -135
  46. data/site/src/config.ts +0 -18
  47. data/site/src/layouts/Layout.astro +0 -85
  48. data/site/src/lib/channels.ts +0 -24
  49. data/site/src/lib/dashboard.ts +0 -269
  50. data/site/src/pages/index.astro +0 -44
  51. data/site/src/pages/library/[slug].astro +0 -128
  52. data/site/src/pages/methodology.astro +0 -55
  53. data/site/src/styles/global.css +0 -103
  54. data/site/tsconfig.json +0 -5
checksums.yaml CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA256:
3
- metadata.gz: ff36b734da92061c2bbf271fd1e94f79f80d844f0b492c7f06a51aca5ed794aa
4
- data.tar.gz: 28aeb4041d3c1c04cdcfd4b5f5ad21757ed0616277bcf34b2db15c9d56a06b5a
3
+ metadata.gz: ed5cf6538b0a64c26b9d9c0739b943f750f30476aa27a94c5b87aae98c203b55
4
+ data.tar.gz: 3d1e7eb5c8f71c4052014729bd6dbbf4417a68339065a7a934ea1e5a3ef82a3b
5
5
  SHA512:
6
- metadata.gz: 9c497b089e84bc674bd444df875cc161ecf97b0d077d2ba9cb3c26cee91c27d8694cabc149b61f78c4fc0f9890b808a7604e6106e1d91aa04595c40a3cb6fa77
7
- data.tar.gz: 5a8eebcfe19699b5d9e1aed3caf1c65bec4937fe51199b8da0ef152e6145deab815621c354495279236f9b7c2e0eaa8e1c70eebdc1353ffb8ff6c89c900afeaa
6
+ metadata.gz: 8bd0e7a6052712f3a49c4656e6aa663cd4db2215c9f9ebc3ac8379b7f258f78e488fdfc46bb52a8e6e9d89cc07ef78fa4fbebe6f0471881b679d40d5ab42284d
7
+ data.tar.gz: 5441d7d92266df86976a78dd4fb68acf8c491147c799b06aa9e1a67ac5bd382dfd27547505e4566483a9657f983bc7bb0ffb5280cc17089de61a8b070fe5677b
@@ -0,0 +1,65 @@
1
+ #!/usr/bin/env bash
2
+ # Pushes one format's results.yaml to serialbench/data via the GitHub
3
+ # Contents API (atomic per-file, no merge conflicts from parallel legs).
4
+ # Called after each format's benchmark completes — the site rebuilds
5
+ # incrementally as data arrives.
6
+ set -euo pipefail
7
+
8
+ FMT="$1"
9
+ RUBY_VERSION="$2"
10
+ PLATFORM="$3"
11
+ RESULTS_FILE="results/runs/ci-ruby-${RUBY_VERSION}-${PLATFORM}/${FMT}/results.yaml"
12
+ DATA_TOKEN="${DATA_REPO_TOKEN:-}"
13
+
14
+ if [ -z "$DATA_TOKEN" ]; then
15
+ echo "::warning::DATA_REPO_TOKEN not set — skipping data push"
16
+ exit 0
17
+ fi
18
+
19
+ if [ ! -f "$RESULTS_FILE" ]; then
20
+ echo "::warning::No results at $RESULTS_FILE — skipping"
21
+ exit 0
22
+ fi
23
+
24
+ DATE=$(date -u +%Y-%m-%d)
25
+ TARGET_PATH="runs/${DATE}/${PLATFORM}-ruby-${RUBY_VERSION}.${FMT}.yaml"
26
+ CONTENT=$(base64 < "$RESULTS_FILE")
27
+
28
+ echo "Pushing ${TARGET_PATH} to serialbench/data..."
29
+
30
+ # Try create; if file exists (422), get sha and update
31
+ HTTP_CODE=$(curl -s -o /tmp/data-push-resp.json -w "%{http_code}" -X PUT \
32
+ -H "Authorization: Bearer ${DATA_TOKEN}" \
33
+ -H "Accept: application/vnd.github+json" \
34
+ "https://api.github.com/repos/serialbench/data/contents/${TARGET_PATH}" \
35
+ -d "{\"message\": \"${PLATFORM} ruby-${RUBY_VERSION} ${FMT}\", \"content\": \"${CONTENT}\", \"branch\": \"main\"}")
36
+
37
+ if [ "$HTTP_CODE" = "200" ] || [ "$HTTP_CODE" = "201" ]; then
38
+ echo "Pushed ${TARGET_PATH}"
39
+ elif [ "$HTTP_CODE" = "422" ]; then
40
+ SHA=$(curl -sf \
41
+ -H "Authorization: Bearer ${DATA_TOKEN}" \
42
+ "https://api.github.com/repos/serialbench/data/contents/${TARGET_PATH}" \
43
+ | grep -oE '"sha":\s*"[a-f0-9]+"' | head -1 | grep -oE '[a-f0-9]{40}')
44
+ if [ -n "$SHA" ]; then
45
+ curl -sf -X PUT \
46
+ -H "Authorization: Bearer ${DATA_TOKEN}" \
47
+ -H "Accept: application/vnd.github+json" \
48
+ "https://api.github.com/repos/serialbench/data/contents/${TARGET_PATH}" \
49
+ -d "{\"message\": \"${PLATFORM} ruby-${RUBY_VERSION} ${FMT} (update)\", \"content\": \"${CONTENT}\", \"sha\": \"${SHA}\", \"branch\": \"main\"}" > /dev/null
50
+ echo "Updated existing ${TARGET_PATH}"
51
+ else
52
+ echo "::warning::422 but couldn't get sha for ${TARGET_PATH}"
53
+ fi
54
+ else
55
+ echo "::warning::Push failed (${HTTP_CODE}): $(cat /tmp/data-push-resp.json | head -c 200)"
56
+ fi
57
+
58
+ # Trigger site rebuild (debounced by concurrency group on the .io repo)
59
+ curl -sf -X POST \
60
+ -H "Authorization: Bearer ${DATA_TOKEN}" \
61
+ -H "Accept: application/vnd.github+json" \
62
+ "https://api.github.com/repos/serialbench/serialbench.github.io/dispatches" \
63
+ -d '{"event_type": "data-updated"}' \
64
+ && echo "Site rebuild triggered" \
65
+ || echo "::warning::Failed to trigger site rebuild"
@@ -16,13 +16,8 @@ on:
16
16
 
17
17
  permissions:
18
18
  contents: read
19
- pages: write
20
- id-token: write
21
19
 
22
20
  concurrency:
23
- # Renamed off "pages": that group's server-side state is wedged (a queued
24
- # run there returns 500 on cancel and blocks the single in-progress slot),
25
- # which starved every benchmark-weekly run after 2026-08-23 10:22Z.
26
21
  group: "site-deploy"
27
22
  cancel-in-progress: false
28
23
 
@@ -76,8 +71,6 @@ jobs:
76
71
  run: |
77
72
  vcpkg install libxml2:${{ steps.windows-arch.outputs.arch }} libxslt:${{ steps.windows-arch.outputs.arch }} 2>&1 || true
78
73
  vcpkg integrate install 2>&1 || true
79
- # vcpkg dynamic triplets put the DLLs in bin/; nokogiri's compiled
80
- # extension needs them on PATH at require time.
81
74
  echo "C:/vcpkg/installed/${{ steps.windows-arch.outputs.arch }}/bin" >> $GITHUB_PATH
82
75
  shell: bash
83
76
 
@@ -87,10 +80,6 @@ jobs:
87
80
  mkdir -p .bundle 2>&1 || true
88
81
  echo "---" > .bundle/config 2>&1 || true
89
82
  echo 'BUNDLE_BUILD__LIBXML___RUBY: "--with-xml2-dir=C:/vcpkg/installed/${{ steps.windows-arch.outputs.arch }} --with-xml2-include=C:/vcpkg/installed/${{ steps.windows-arch.outputs.arch }}/include/libxml2 --with-xml2-lib=C:/vcpkg/installed/${{ steps.windows-arch.outputs.arch }}/lib"' >> .bundle/config 2>&1 || true
90
- # windows-11-arm has no precompiled nokogiri (pulled transitively via
91
- # moxml); build it against the vcpkg libxml2 instead of the vendored
92
- # source build that fails on ucrt/ARM64. Harmless on x64 Windows,
93
- # where the precompiled gem makes this config moot.
94
83
  echo 'BUNDLE_BUILD__NOKOGIRI: "--use-system-libraries --with-xml2-include=C:/vcpkg/installed/${{ steps.windows-arch.outputs.arch }}/include/libxml2 --with-xml2-lib=C:/vcpkg/installed/${{ steps.windows-arch.outputs.arch }}/lib --with-xslt-include=C:/vcpkg/installed/${{ steps.windows-arch.outputs.arch }}/include/libxslt --with-xslt-lib=C:/vcpkg/installed/${{ steps.windows-arch.outputs.arch }}/lib --with-zlib-dir=C:/vcpkg/installed/${{ steps.windows-arch.outputs.arch }}"' >> .bundle/config 2>&1 || true
95
84
  shell: bash
96
85
 
@@ -100,14 +89,10 @@ jobs:
100
89
  ruby-version: ${{ matrix.ruby-version }}
101
90
  bundler-cache: true
102
91
 
103
- # The directory of ruby.exe is always in the DLL search path (unlike
104
- # PATH manipulation across step boundaries), so stage the vcpkg DLLs
105
- # there for the system-built nokogiri on Windows ARM.
106
92
  - name: Stage vcpkg DLLs beside ruby.exe (Windows)
107
93
  if: startsWith(matrix.platform, 'windows-')
108
94
  run: |
109
95
  RUBY_BIN="$(dirname "$(command -v ruby)")"
110
- echo "Staging vcpkg DLLs into $RUBY_BIN"
111
96
  ls "C:/vcpkg/installed/${{ steps.windows-arch.outputs.arch }}/bin/" || true
112
97
  cp -f "C:/vcpkg/installed/${{ steps.windows-arch.outputs.arch }}/bin/"*.dll "$RUBY_BIN/" 2>&1 || true
113
98
  shell: bash
@@ -123,48 +108,29 @@ jobs:
123
108
  run: |
124
109
  brew install libxml2 libxslt
125
110
 
126
- - name: Debug Ruby platform (Windows only)
127
- if: startsWith(matrix.platform, 'windows-')
128
- shell: ruby {0}
129
- run: |
130
- puts "=== Ruby Platform Debug Info ==="
131
- puts "RUBY_PLATFORM: #{RUBY_PLATFORM}"
132
- puts "Gem.win_platform?: #{Gem.win_platform?}"
133
- puts "RbConfig::CONFIG['host_os']: #{RbConfig::CONFIG['host_os']}"
134
- puts "RbConfig::CONFIG['host_cpu']: #{RbConfig::CONFIG['host_cpu']}"
135
- puts "RbConfig::CONFIG['arch']: #{RbConfig::CONFIG['arch']}"
136
- puts "================================"
137
-
138
111
  - name: Install gems
139
112
  run: bundle install
140
113
 
141
- # ubuntu-22.04's glibc (2.35) predates the precompiled leptris gem's
142
- # build host, so the gem's vendored libleptris.so fails to dlopen there
143
- # and the adapter reports leptris unavailable (empty availability dots
144
- # on the site). Leptris is pure C99 — build the lib from the gem's
145
- # tagged source and point the FFI loader at it; LEPTRIS_LIB_PATH is the
146
- # first candidate in the gem's ffi_lib list.
147
114
  - name: Build libleptris from source (Ubuntu 22.04)
148
115
  if: matrix.platform == 'ubuntu-22.04' || matrix.platform == 'ubuntu-22.04-arm'
149
116
  run: |
150
- LEPTRIS_VERSION=$(bundle exec ruby -e "require 'leptris'; print Leptris::VERSION")
151
- echo "Building libleptris ${LEPTRIS_VERSION}"
152
- curl -sL "https://github.com/leptris/leptris/archive/refs/tags/v${LEPTRIS_VERSION}.tar.gz" | tar xz
117
+ LEPTRIS_VERSION=$(bundle exec ruby -e "print Gem::Specification.find_by_name('leptris').version")
118
+ LEPTRIS_TAG=$(curl -s "https://api.github.com/repos/leptris/leptris/tags?per_page=100" \
119
+ | grep -oE '"v[0-9]+\.[0-9]+\.[0-9]+"' | tr -d '"' | sort -V \
120
+ | awk -v v="v${LEPTRIS_VERSION}" '$0 <= v' | tail -1)
121
+ echo "Building libleptris ${LEPTRIS_VERSION} from tag ${LEPTRIS_TAG}"
122
+ test -n "${LEPTRIS_TAG}"
123
+ curl -sL "https://github.com/leptris/leptris/archive/refs/tags/${LEPTRIS_TAG}.tar.gz" | tar xz
124
+ ln -s "leptris-${LEPTRIS_TAG#v}" "leptris-${LEPTRIS_VERSION}"
153
125
  cmake -S "leptris-${LEPTRIS_VERSION}" -B /tmp/leptris-build \
154
126
  -DLEPTRIS_BUILD_SHARED=ON -DLEPTRIS_BUILD_STATIC=OFF -DBUILD_TESTING=OFF \
155
127
  -DLEPTRIS_BUILD_CLI=OFF -DLEPTRIS_BUILD_BENCHMARKS=OFF -DLEPTRIS_BUILD_MAN_PAGES=OFF \
156
128
  -DLEPTRIS_ENABLE_UTF8PROC=OFF -DLEPTRIS_ENABLE_ICONV=OFF
157
129
  cmake --build /tmp/leptris-build -j"$(nproc)"
158
130
  LIBLEPTRIS=$(find /tmp/leptris-build -name 'libleptris.so*' -type f | head -1)
159
- echo "Built ${LIBLEPTRIS}"
160
131
  echo "LEPTRIS_LIB_PATH=${LIBLEPTRIS}" >> "$GITHUB_ENV"
161
132
  shell: bash
162
133
 
163
- - name: Update Ruby-Build cache
164
- run: bundle exec serialbench ruby-build update
165
- env:
166
- GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}
167
-
168
134
  - name: Create environment config
169
135
  run: |
170
136
  mkdir -p config/environments
@@ -178,135 +144,124 @@ jobs:
178
144
  EOF
179
145
  shell: bash
180
146
 
181
- - name: Run benchmarks
147
+ # Each format is an independent checkpoint with its own upload.
148
+ # A failure in one format doesn't prevent the others from uploading.
149
+ - name: Benchmark xml
150
+ continue-on-error: true
151
+ shell: bash
182
152
  env:
183
153
  GITHUB_RUNNER_PLATFORM: ${{ matrix.platform }}
184
154
  run: |
185
- bundle exec serialbench environment execute config/environments/ci-ruby-${{ matrix.ruby-version }}.yml config/benchmarks/full.yml results/runs/ci-ruby-${{ matrix.ruby-version }}-${{ matrix.platform }}
186
-
187
- - name: Verify benchmark results before upload
188
- run: |
189
- echo "=== Verifying benchmark results ==="
190
- RESULTS_FILE="results/runs/ci-ruby-${{ matrix.ruby-version }}-${{ matrix.platform }}/results.yaml"
155
+ bundle exec serialbench environment execute \
156
+ config/environments/ci-ruby-${{ matrix.ruby-version }}.yml \
157
+ config/benchmarks/full-xml.yml \
158
+ "results/runs/ci-ruby-${{ matrix.ruby-version }}-${{ matrix.platform }}/xml"
191
159
 
192
- echo "📁 Checking file exists..."
193
- if [ ! -f "$RESULTS_FILE" ]; then
194
- echo "❌ ERROR: results.yaml not found at $RESULTS_FILE"
195
- exit 1
196
- fi
197
-
198
- echo "📊 Checking file size..."
199
- SIZE=$(wc -c < "$RESULTS_FILE" | tr -d ' ')
200
- echo " File size: $SIZE bytes"
201
-
202
- if [ "$SIZE" -lt 1000 ]; then
203
- echo "❌ ERROR: results.yaml is suspiciously small ($SIZE bytes)"
204
- echo " Expected at least 1000 bytes for valid benchmark results"
205
- echo "=== File contents ==="
206
- cat "$RESULTS_FILE"
207
- exit 1
208
- fi
160
+ - name: Upload xml
161
+ if: ${{ !cancelled() }}
162
+ uses: actions/upload-artifact@v4
163
+ with:
164
+ name: benchmark-results-${{ matrix.platform }}-ruby-${{ matrix.ruby-version }}-xml
165
+ path: results/runs/ci-ruby-${{ matrix.ruby-version }}-${{ matrix.platform }}/xml
166
+ retention-days: 30
167
+ if-no-files-found: warn
209
168
 
210
- echo "✅ File size OK: $SIZE bytes"
169
+ - name: Push xml to data repo
170
+ if: ${{ !cancelled() }}
171
+ continue-on-error: true
172
+ env:
173
+ DATA_REPO_TOKEN: ${{ secrets.DATA_REPO_TOKEN }}
174
+ run: .github/scripts/push-to-data.sh xml ${{ matrix.ruby-version }} ${{ matrix.platform }}
211
175
  shell: bash
212
176
 
213
- - name: Validate YAML schema
177
+ - name: Benchmark json
178
+ continue-on-error: true
179
+ shell: bash
180
+ env:
181
+ GITHUB_RUNNER_PLATFORM: ${{ matrix.platform }}
214
182
  run: |
215
- bundle exec serialbench validate result results/runs/ci-ruby-${{ matrix.ruby-version }}-${{ matrix.platform }}/results.yaml
183
+ bundle exec serialbench environment execute \
184
+ config/environments/ci-ruby-${{ matrix.ruby-version }}.yml \
185
+ config/benchmarks/full-json.yml \
186
+ "results/runs/ci-ruby-${{ matrix.ruby-version }}-${{ matrix.platform }}/json"
216
187
 
217
- - name: Upload benchmark results
188
+ - name: Upload json
189
+ if: ${{ !cancelled() }}
218
190
  uses: actions/upload-artifact@v4
219
191
  with:
220
- name: benchmark-results-${{ matrix.platform }}-ruby-${{ matrix.ruby-version }}
221
- path: results/runs/ci-ruby-${{ matrix.ruby-version }}-${{ matrix.platform }}
192
+ name: benchmark-results-${{ matrix.platform }}-ruby-${{ matrix.ruby-version }}-json
193
+ path: results/runs/ci-ruby-${{ matrix.ruby-version }}-${{ matrix.platform }}/json
222
194
  retention-days: 30
195
+ if-no-files-found: warn
223
196
 
224
- # Aggregate results and deploy to GitHub Pages
225
- deploy-pages:
226
- if: github.ref == 'refs/heads/main'
227
- runs-on: ubuntu-latest
228
- needs: [setup, benchmark]
229
- environment:
230
- name: github-pages
231
- url: ${{ steps.deployment.outputs.page_url }}
232
-
233
- steps:
234
- - name: Checkout repository
235
- uses: actions/checkout@v4
236
-
237
- - name: Set up Ruby
238
- uses: ruby/setup-ruby@v1
239
- with:
240
- ruby-version: '3.3'
241
- bundler-cache: true
197
+ - name: Push json to data repo
198
+ if: ${{ !cancelled() }}
199
+ continue-on-error: true
200
+ env:
201
+ DATA_REPO_TOKEN: ${{ secrets.DATA_REPO_TOKEN }}
202
+ run: .github/scripts/push-to-data.sh json ${{ matrix.ruby-version }} ${{ matrix.platform }}
203
+ shell: bash
242
204
 
243
- - name: Install system dependencies
205
+ - name: Benchmark yaml
206
+ continue-on-error: true
207
+ shell: bash
208
+ env:
209
+ GITHUB_RUNNER_PLATFORM: ${{ matrix.platform }}
244
210
  run: |
245
- sudo apt-get update
246
- sudo apt-get install -y libxml2-dev libxslt1-dev build-essential
247
-
248
- - name: Install gems
249
- run: bundle install
211
+ bundle exec serialbench environment execute \
212
+ config/environments/ci-ruby-${{ matrix.ruby-version }}.yml \
213
+ config/benchmarks/full-yaml.yml \
214
+ "results/runs/ci-ruby-${{ matrix.ruby-version }}-${{ matrix.platform }}/yaml"
250
215
 
251
- - name: Download all benchmark artifacts
252
- uses: actions/download-artifact@v4
216
+ - name: Upload yaml
217
+ if: ${{ !cancelled() }}
218
+ uses: actions/upload-artifact@v4
253
219
  with:
254
- pattern: benchmark-results-*
255
- path: artifacts/
256
-
257
- - name: List downloaded artifacts structure
258
- run: |
259
- echo "=== Artifacts directory structure ==="
260
- ls -la artifacts/
261
- echo ""
262
- echo "=== Searching for results.yaml files ==="
263
- find artifacts/ -name "results.yaml" -type f
264
- echo ""
265
- echo "=== Directory tree (first 3 levels) ==="
266
- find artifacts/ -maxdepth 3 -type d | sort
267
-
268
- - name: Create resultset
269
- run: |
270
- mkdir -p results/sets
271
- bundle exec serialbench resultset create weekly-benchmark results/sets/weekly-benchmark
272
-
273
- - name: Add all results to resultset
274
- run: |
275
- bundle exec serialbench resultset add-result results/sets/weekly-benchmark artifacts/benchmark-results-*/
276
-
277
- - name: Export dashboard payload and raw data
278
- run: |
279
- bundle exec serialbench resultset export-data results/sets/weekly-benchmark site/src/data/sample.json --raw-data-dir site/public/data
220
+ name: benchmark-results-${{ matrix.platform }}-ruby-${{ matrix.ruby-version }}-yaml
221
+ path: results/runs/ci-ruby-${{ matrix.ruby-version }}-${{ matrix.platform }}/yaml
222
+ retention-days: 30
223
+ if-no-files-found: warn
280
224
 
281
- - name: Set up Node
282
- uses: actions/setup-node@v4
283
- with:
284
- node-version: '24'
285
- cache: npm
286
- cache-dependency-path: site/package-lock.json
225
+ - name: Push yaml to data repo
226
+ if: ${{ !cancelled() }}
227
+ continue-on-error: true
228
+ env:
229
+ DATA_REPO_TOKEN: ${{ secrets.DATA_REPO_TOKEN }}
230
+ run: .github/scripts/push-to-data.sh yaml ${{ matrix.ruby-version }} ${{ matrix.platform }}
231
+ shell: bash
287
232
 
288
- - name: Build site
233
+ - name: Benchmark toml
234
+ continue-on-error: true
235
+ shell: bash
236
+ env:
237
+ GITHUB_RUNNER_PLATFORM: ${{ matrix.platform }}
289
238
  run: |
290
- cd site
291
- npm ci
292
- npm run build
239
+ bundle exec serialbench environment execute \
240
+ config/environments/ci-ruby-${{ matrix.ruby-version }}.yml \
241
+ config/benchmarks/full-toml.yml \
242
+ "results/runs/ci-ruby-${{ matrix.ruby-version }}-${{ matrix.platform }}/toml"
293
243
 
294
- - name: Setup Pages
295
- uses: actions/configure-pages@v4
296
-
297
- - name: Upload to GitHub Pages
298
- uses: actions/upload-pages-artifact@v3
244
+ - name: Upload toml
245
+ if: ${{ !cancelled() }}
246
+ uses: actions/upload-artifact@v4
299
247
  with:
300
- path: site/dist
248
+ name: benchmark-results-${{ matrix.platform }}-ruby-${{ matrix.ruby-version }}-toml
249
+ path: results/runs/ci-ruby-${{ matrix.ruby-version }}-${{ matrix.platform }}/toml
250
+ retention-days: 30
251
+ if-no-files-found: warn
301
252
 
302
- - name: Deploy to GitHub Pages
303
- id: deployment
304
- uses: actions/deploy-pages@v4
253
+ - name: Push toml to data repo
254
+ if: ${{ !cancelled() }}
255
+ continue-on-error: true
256
+ env:
257
+ DATA_REPO_TOKEN: ${{ secrets.DATA_REPO_TOKEN }}
258
+ run: .github/scripts/push-to-data.sh toml ${{ matrix.ruby-version }} ${{ matrix.platform }}
259
+ shell: bash
305
260
 
306
261
  # Summary job
307
262
  summary:
308
263
  runs-on: ubuntu-latest
309
- needs: [setup, benchmark, deploy-pages]
264
+ needs: [setup, benchmark]
310
265
  if: always()
311
266
  steps:
312
267
  - name: Generate workflow summary
@@ -314,28 +269,19 @@ jobs:
314
269
  echo "## Weekly Benchmark Summary" >> $GITHUB_STEP_SUMMARY
315
270
  echo "" >> $GITHUB_STEP_SUMMARY
316
271
  echo "**Benchmark Status**: ${{ needs.benchmark.result }}" >> $GITHUB_STEP_SUMMARY
317
- echo "**Deploy Status**: ${{ needs.deploy-pages.result }}" >> $GITHUB_STEP_SUMMARY
272
+ echo "**Incremental pushes**: each format pushes to data repo on completion" >> $GITHUB_STEP_SUMMARY
318
273
  echo "" >> $GITHUB_STEP_SUMMARY
319
274
  echo "### Platforms Tested" >> $GITHUB_STEP_SUMMARY
320
- echo "- Ubuntu Latest (Linux x86_64)" >> $GITHUB_STEP_SUMMARY
321
- echo "- Ubuntu 24.04 (Linux ARM64)" >> $GITHUB_STEP_SUMMARY
322
- echo "- Ubuntu 22.04 (Linux ARM64)" >> $GITHUB_STEP_SUMMARY
323
- echo "- macOS 14 (Apple Silicon ARM64)" >> $GITHUB_STEP_SUMMARY
324
- echo "- macOS 15 (Apple Silicon ARM64)" >> $GITHUB_STEP_SUMMARY
325
- echo "- macOS 15 Intel (Intel x86_64)" >> $GITHUB_STEP_SUMMARY
326
- echo "- macOS 26 (Apple Silicon ARM64)" >> $GITHUB_STEP_SUMMARY
327
- echo "- macOS 26 Intel (Intel x86_64)" >> $GITHUB_STEP_SUMMARY
275
+ echo "- Ubuntu 24.04 (x86_64 + ARM64)" >> $GITHUB_STEP_SUMMARY
276
+ echo "- Ubuntu 22.04 (x86_64 + ARM64)" >> $GITHUB_STEP_SUMMARY
277
+ echo "- macOS 14, 15, 26 (ARM64 + Intel)" >> $GITHUB_STEP_SUMMARY
278
+ echo "- Windows 2022, 2025, 11-ARM" >> $GITHUB_STEP_SUMMARY
328
279
  echo "" >> $GITHUB_STEP_SUMMARY
329
280
  echo "### Ruby Versions" >> $GITHUB_STEP_SUMMARY
330
281
  echo "- Ruby 3.2, 3.3, 3.4, 4.0" >> $GITHUB_STEP_SUMMARY
331
282
  echo "" >> $GITHUB_STEP_SUMMARY
332
- echo "### Serialization Libraries" >> $GITHUB_STEP_SUMMARY
333
- echo "- **XML**: REXML, Ox, Nokogiri, Oga, LibXML, Leptris" >> $GITHUB_STEP_SUMMARY
334
- echo "- **JSON**: JSON, Oj, RapidJSON, YAJL" >> $GITHUB_STEP_SUMMARY
335
- echo "- **YAML**: Psych" >> $GITHUB_STEP_SUMMARY
336
- echo "- **TOML**: TOML-RB, Tomlib, tomlrb" >> $GITHUB_STEP_SUMMARY
337
- echo "" >> $GITHUB_STEP_SUMMARY
338
283
  if [ "${{ github.ref }}" == "refs/heads/main" ]; then
339
284
  echo "### Results" >> $GITHUB_STEP_SUMMARY
340
- echo "📊 [View Interactive Dashboard](https://metanorma.github.io/serialbench/)" >> $GITHUB_STEP_SUMMARY
285
+ echo "📊 [View Dashboard](https://serialbench.github.io/serialbench/)" >> $GITHUB_STEP_SUMMARY
286
+ echo "📦 [Raw Data](https://github.com/serialbench/data)" >> $GITHUB_STEP_SUMMARY
341
287
  fi
@@ -1,5 +1,3 @@
1
- # Auto-generated by Cimas: Do not edit it manually!
2
- # See https://github.com/metanorma/cimas
3
1
  name: release
4
2
 
5
3
  on:
@@ -7,19 +5,76 @@ on:
7
5
  inputs:
8
6
  next_version:
9
7
  description: |
10
- Next release version. Possible values: x.y.z, major, minor, patch (or pre|rc|etc).
11
- Also, you can pass 'skip' to skip 'git tag' and do 'gem push' for the current version
8
+ Next release version. Possible values: x.y.z, major, minor, patch
9
+ (or pre|rc|etc).
12
10
  required: true
13
- default: 'skip'
14
- repository_dispatch:
15
- types: [ do-release ]
11
+ default: 'minor'
12
+ push:
13
+ tags: ['v*']
14
+
15
+ permissions:
16
+ contents: write
17
+ id-token: write
16
18
 
17
19
  jobs:
18
20
  release:
19
- uses: metanorma/ci/.github/workflows/rubygems-release.yml@main
20
- with:
21
- next_version: ${{ github.event.inputs.next_version }}
22
- secrets:
23
- rubygems-api-key: ${{ secrets.METANORMA_CI_RUBYGEMS_API_KEY }}
24
- pat_token: ${{ secrets.METANORMA_CI_PAT_TOKEN }}
21
+ runs-on: ubuntu-latest
22
+ steps:
23
+ - uses: actions/checkout@v4
24
+
25
+ - uses: ruby/setup-ruby@v1
26
+ with:
27
+ ruby-version: '3.4'
28
+ bundler-cache: true
29
+
30
+ - name: Determine version
31
+ id: version
32
+ run: |
33
+ INPUT="${{ github.event.inputs.next_version }}"
34
+ if [ -z "$INPUT" ]; then
35
+ INPUT="${GITHUB_REF#refs/tags/v}"
36
+ echo "version=${INPUT}" >> "$GITHUB_OUTPUT"
37
+ elif echo "$INPUT" | grep -qE '^[0-9]+\.[0-9]+\.[0-9]+'; then
38
+ echo "version=${INPUT}" >> "$GITHUB_OUTPUT"
39
+ else
40
+ CURRENT=$(ruby -e "print Gem::Specification.load('serialbench.gemspec').version.to_s")
41
+ case "${INPUT}" in
42
+ major) NEW=$(echo "$CURRENT" | awk -F. '{print $1+1".0.0"}') ;;
43
+ minor) NEW=$(echo "$CURRENT" | awk -F. '{print $1"."$2+1".0"}') ;;
44
+ patch) NEW=$(echo "$CURRENT" | awk -F. '{print $1"."$2"."$3+1}') ;;
45
+ *) NEW="${INPUT}" ;;
46
+ esac
47
+ echo "version=${NEW}" >> "$GITHUB_OUTPUT"
48
+ fi
49
+
50
+ - name: Update version
51
+ run: |
52
+ VERSION=${{ steps.version.outputs.version }}
53
+ sed -i.bak "s/VERSION = .*/VERSION = '${VERSION}'/" lib/serialbench/version.rb
54
+ rm -f lib/serialbench/version.rb.bak
55
+ git config user.name "release-bot"
56
+ git config user.email "release-bot@users.noreply.github.com"
57
+ git add lib/serialbench/version.rb
58
+ git commit -m "Bump serialbench to ${VERSION}" || exit 0
59
+ git push origin HEAD:main
60
+
61
+ - name: Tag
62
+ run: |
63
+ VERSION=${{ steps.version.outputs.version }}
64
+ git tag "v${VERSION}" 2>/dev/null || true
65
+ git push origin "v${VERSION}" 2>/dev/null || true
66
+
67
+ - name: Build gem
68
+ run: gem build serialbench.gemspec
69
+
70
+ - name: Push to RubyGems
71
+ run: gem push serialbench-*.gem
72
+ env:
73
+ GEM_HOST_API_KEY: ${{ secrets.RUBYGEMS_API_KEY }}
25
74
 
75
+ - name: Create GitHub Release
76
+ run: |
77
+ VERSION=${{ steps.version.outputs.version }}
78
+ gh release create "v${VERSION}" --title "serialbench ${VERSION}" --generate-notes 2>/dev/null || true
79
+ env:
80
+ GH_TOKEN: ${{ secrets.GITHUB_TOKEN }}
data/Gemfile CHANGED
@@ -12,7 +12,7 @@ unless Gem.win_platform? && RUBY_PLATFORM.include?('aarch64')
12
12
  gem 'libxml-ruby'
13
13
  end
14
14
 
15
- gem 'leptris' # Needs the libleptris shared library (LEPTRIS_LIB_PATH or system install)
15
+ gem 'leptris', '1.9.0' # pin to latest git tag; newer gems expect APIs not in v1.9.0 source builds # Needs the libleptris shared library (LEPTRIS_LIB_PATH or system install)
16
16
  gem 'benchmark' # Removed from stdlib in Ruby 4.0
17
17
  gem 'base64' # Required for Ruby 3.4+
18
18
  gem 'lutaml-model', '~> 0.7'
@@ -0,0 +1,25 @@
1
+ # Per-format split of full.yml: each format runs in its own process so
2
+ # memory profiling of large documents cannot compound across formats
3
+ # (windows runners OOMed with all four formats in one process).
4
+ name: full-json
5
+
6
+ data_sizes:
7
+ - small
8
+ - medium
9
+ - large
10
+
11
+ formats:
12
+ - json
13
+
14
+ iterations:
15
+ small: 10
16
+ medium: 3
17
+ large: 1
18
+
19
+ operations:
20
+ - parse
21
+ - generate
22
+ - streaming
23
+ - memory
24
+
25
+ warmup: 2
@@ -0,0 +1,25 @@
1
+ # Per-format split of full.yml: each format runs in its own process so
2
+ # memory profiling of large documents cannot compound across formats
3
+ # (windows runners OOMed with all four formats in one process).
4
+ name: full-toml
5
+
6
+ data_sizes:
7
+ - small
8
+ - medium
9
+ - large
10
+
11
+ formats:
12
+ - toml
13
+
14
+ iterations:
15
+ small: 10
16
+ medium: 3
17
+ large: 1
18
+
19
+ operations:
20
+ - parse
21
+ - generate
22
+ - streaming
23
+ - memory
24
+
25
+ warmup: 2
@@ -0,0 +1,26 @@
1
+ # Per-format split of full.yml: each format runs in its own process so
2
+ # memory profiling of large documents cannot compound across formats
3
+ # (windows runners OOMed with all four formats in one process).
4
+ name: full-xml
5
+
6
+ data_sizes:
7
+ - small
8
+ - medium
9
+ - large
10
+
11
+ formats:
12
+ - xml
13
+
14
+ iterations:
15
+ small: 10
16
+ medium: 3
17
+ large: 1
18
+
19
+ operations:
20
+ - parse
21
+ - generate
22
+ - streaming
23
+ - xpath
24
+ - memory
25
+
26
+ warmup: 2
@@ -0,0 +1,25 @@
1
+ # Per-format split of full.yml: each format runs in its own process so
2
+ # memory profiling of large documents cannot compound across formats
3
+ # (windows runners OOMed with all four formats in one process).
4
+ name: full-yaml
5
+
6
+ data_sizes:
7
+ - small
8
+ - medium
9
+ - large
10
+
11
+ formats:
12
+ - yaml
13
+
14
+ iterations:
15
+ small: 10
16
+ medium: 3
17
+ large: 1
18
+
19
+ operations:
20
+ - parse
21
+ - generate
22
+ - streaming
23
+ - memory
24
+
25
+ warmup: 2