serialbench 0.1.3 → 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 (40) hide show
  1. checksums.yaml +4 -4
  2. data/.github/scripts/push-to-data.sh +65 -0
  3. data/.github/workflows/benchmark.yml +134 -168
  4. data/.github/workflows/release.yml +68 -13
  5. data/Gemfile +2 -0
  6. data/README.adoc +5 -0
  7. data/config/benchmarks/full-json.yml +25 -0
  8. data/config/benchmarks/full-toml.yml +25 -0
  9. data/config/benchmarks/full-xml.yml +26 -0
  10. data/config/benchmarks/full-yaml.yml +25 -0
  11. data/config/benchmarks/full.yml +9 -4
  12. data/lib/serialbench/benchmark_runner.rb +20 -23
  13. data/lib/serialbench/cli/benchmark_cli.rb +1 -1
  14. data/lib/serialbench/cli/resultset_cli.rb +40 -0
  15. data/lib/serialbench/cli.rb +1 -8
  16. data/lib/serialbench/models/benchmark_result.rb +2 -0
  17. data/lib/serialbench/models/platform.rb +5 -2
  18. data/lib/serialbench/serializers/base_serializer.rb +14 -2
  19. data/lib/serialbench/serializers/json/rapidjson_serializer.rb +0 -4
  20. data/lib/serialbench/serializers/xml/base_xml_serializer.rb +6 -5
  21. data/lib/serialbench/serializers/xml/leptris_serializer.rb +174 -0
  22. data/lib/serialbench/serializers/xml/libxml_serializer.rb +9 -0
  23. data/lib/serialbench/serializers/xml/nokogiri_serializer.rb +4 -0
  24. data/lib/serialbench/serializers/xml/oga_serializer.rb +8 -0
  25. data/lib/serialbench/serializers/yaml/base_yaml_serializer.rb +1 -3
  26. data/lib/serialbench/serializers/yaml/psych_serializer.rb +0 -4
  27. data/lib/serialbench/serializers.rb +3 -1
  28. data/lib/serialbench/site_generator.rb +56 -2
  29. data/lib/serialbench/version.rb +1 -1
  30. data/lib/serialbench.rb +1 -1
  31. metadata +9 -15
  32. data/lib/serialbench/templates/assets/css/benchmark_report.css +0 -535
  33. data/lib/serialbench/templates/assets/css/format_based.css +0 -474
  34. data/lib/serialbench/templates/assets/css/themes.css +0 -589
  35. data/lib/serialbench/templates/assets/js/chart_helpers.js +0 -411
  36. data/lib/serialbench/templates/assets/js/dashboard.js +0 -795
  37. data/lib/serialbench/templates/assets/js/navigation.js +0 -142
  38. data/lib/serialbench/templates/base.liquid +0 -49
  39. data/lib/serialbench/templates/format_based.liquid +0 -507
  40. data/lib/serialbench/templates/partials/chart_section.liquid +0 -4
checksums.yaml CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA256:
3
- metadata.gz: c24dcb07a68058a2ff622be5f16e6c7225cd266bf29c3fcd06a0ecd597b9b8d3
4
- data.tar.gz: 95833392ca0fe8cab20d7d0300cd86f11948a2e0d766885e6dff0de2b75189b1
3
+ metadata.gz: ed5cf6538b0a64c26b9d9c0739b943f750f30476aa27a94c5b87aae98c203b55
4
+ data.tar.gz: 3d1e7eb5c8f71c4052014729bd6dbbf4417a68339065a7a934ea1e5a3ef82a3b
5
5
  SHA512:
6
- metadata.gz: 8e1b7c78643b32cf34251220cd9dac61db43fa16cf104669b2882b139faad9bb1051a3a552d5caf37fc8018014c0dda6bcbe35870688e3ea229c64c5c8064d5e
7
- data.tar.gz: d5c0727a5d5d24d82107837b996f8a31013bcf75a66a737ce6087767858c7b54b59ad9ed9014cf84d0ef3f4c07d5954bcfa3aa0698d3f745bb984477f18b880f
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,11 +16,9 @@ on:
16
16
 
17
17
  permissions:
18
18
  contents: read
19
- pages: write
20
- id-token: write
21
19
 
22
20
  concurrency:
23
- group: "pages"
21
+ group: "site-deploy"
24
22
  cancel-in-progress: false
25
23
 
26
24
  jobs:
@@ -33,8 +31,8 @@ jobs:
33
31
  - name: Set matrix configurations
34
32
  id: set-matrix
35
33
  run: |
36
- echo 'ruby-versions=["3.1", "3.2", "3.3", "3.4"]' >> $GITHUB_OUTPUT
37
- echo 'platforms=["ubuntu-24.04", "ubuntu-24.04-arm", "ubuntu-22.04", "ubuntu-22.04-arm", "macos-13", "macos-15-intel", "macos-14", "macos-15", "macos-26", "windows-2022", "windows-2025", "windows-11-arm"]' >> $GITHUB_OUTPUT
34
+ echo 'ruby-versions=["3.2", "3.3", "3.4", "4.0"]' >> $GITHUB_OUTPUT
35
+ echo 'platforms=["ubuntu-24.04", "ubuntu-24.04-arm", "ubuntu-22.04", "ubuntu-22.04-arm", "macos-14", "macos-15", "macos-15-intel", "macos-26", "macos-26-intel", "windows-2022", "windows-2025", "windows-11-arm"]' >> $GITHUB_OUTPUT
38
36
 
39
37
  # Cross-platform native benchmarks
40
38
  benchmark:
@@ -46,9 +44,8 @@ jobs:
46
44
  platform: ${{ fromJson(needs.setup.outputs.platforms) }}
47
45
  ruby-version: ${{ fromJson(needs.setup.outputs.ruby-versions) }}
48
46
  exclude:
49
- # windows-11-arm only supports Ruby 3.4.x
50
- - platform: windows-11-arm
51
- ruby-version: "3.1"
47
+ # RubyInstaller ships no arm64 builds for Ruby 3.2/3.3;
48
+ # windows-11-arm runs 3.4.x and 4.x only
52
49
  - platform: windows-11-arm
53
50
  ruby-version: "3.2"
54
51
  - platform: windows-11-arm
@@ -72,8 +69,9 @@ jobs:
72
69
  - name: Install vcpkg dependencies (Windows)
73
70
  if: startsWith(matrix.platform, 'windows-')
74
71
  run: |
75
- vcpkg install libxml2:${{ steps.windows-arch.outputs.arch }} 2>&1 || true
72
+ vcpkg install libxml2:${{ steps.windows-arch.outputs.arch }} libxslt:${{ steps.windows-arch.outputs.arch }} 2>&1 || true
76
73
  vcpkg integrate install 2>&1 || true
74
+ echo "C:/vcpkg/installed/${{ steps.windows-arch.outputs.arch }}/bin" >> $GITHUB_PATH
77
75
  shell: bash
78
76
 
79
77
  - name: Configure bundler for libxml2 (Windows)
@@ -82,6 +80,7 @@ jobs:
82
80
  mkdir -p .bundle 2>&1 || true
83
81
  echo "---" > .bundle/config 2>&1 || true
84
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
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
85
84
  shell: bash
86
85
 
87
86
  - name: Set up Ruby ${{ matrix.ruby-version }}
@@ -90,6 +89,14 @@ jobs:
90
89
  ruby-version: ${{ matrix.ruby-version }}
91
90
  bundler-cache: true
92
91
 
92
+ - name: Stage vcpkg DLLs beside ruby.exe (Windows)
93
+ if: startsWith(matrix.platform, 'windows-')
94
+ run: |
95
+ RUBY_BIN="$(dirname "$(command -v ruby)")"
96
+ ls "C:/vcpkg/installed/${{ steps.windows-arch.outputs.arch }}/bin/" || true
97
+ cp -f "C:/vcpkg/installed/${{ steps.windows-arch.outputs.arch }}/bin/"*.dll "$RUBY_BIN/" 2>&1 || true
98
+ shell: bash
99
+
93
100
  - name: Install system dependencies (Ubuntu)
94
101
  if: startsWith(matrix.platform, 'ubuntu-')
95
102
  run: |
@@ -101,25 +108,28 @@ jobs:
101
108
  run: |
102
109
  brew install libxml2 libxslt
103
110
 
104
- - name: Debug Ruby platform (Windows only)
105
- if: startsWith(matrix.platform, 'windows-')
106
- shell: ruby {0}
107
- run: |
108
- puts "=== Ruby Platform Debug Info ==="
109
- puts "RUBY_PLATFORM: #{RUBY_PLATFORM}"
110
- puts "Gem.win_platform?: #{Gem.win_platform?}"
111
- puts "RbConfig::CONFIG['host_os']: #{RbConfig::CONFIG['host_os']}"
112
- puts "RbConfig::CONFIG['host_cpu']: #{RbConfig::CONFIG['host_cpu']}"
113
- puts "RbConfig::CONFIG['arch']: #{RbConfig::CONFIG['arch']}"
114
- puts "================================"
115
-
116
111
  - name: Install gems
117
112
  run: bundle install
118
113
 
119
- - name: Update Ruby-Build cache
120
- run: bundle exec serialbench ruby-build update
121
- env:
122
- GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}
114
+ - name: Build libleptris from source (Ubuntu 22.04)
115
+ if: matrix.platform == 'ubuntu-22.04' || matrix.platform == 'ubuntu-22.04-arm'
116
+ run: |
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}"
125
+ cmake -S "leptris-${LEPTRIS_VERSION}" -B /tmp/leptris-build \
126
+ -DLEPTRIS_BUILD_SHARED=ON -DLEPTRIS_BUILD_STATIC=OFF -DBUILD_TESTING=OFF \
127
+ -DLEPTRIS_BUILD_CLI=OFF -DLEPTRIS_BUILD_BENCHMARKS=OFF -DLEPTRIS_BUILD_MAN_PAGES=OFF \
128
+ -DLEPTRIS_ENABLE_UTF8PROC=OFF -DLEPTRIS_ENABLE_ICONV=OFF
129
+ cmake --build /tmp/leptris-build -j"$(nproc)"
130
+ LIBLEPTRIS=$(find /tmp/leptris-build -name 'libleptris.so*' -type f | head -1)
131
+ echo "LEPTRIS_LIB_PATH=${LIBLEPTRIS}" >> "$GITHUB_ENV"
132
+ shell: bash
123
133
 
124
134
  - name: Create environment config
125
135
  run: |
@@ -134,160 +144,124 @@ jobs:
134
144
  EOF
135
145
  shell: bash
136
146
 
137
- - 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
138
152
  env:
139
153
  GITHUB_RUNNER_PLATFORM: ${{ matrix.platform }}
140
154
  run: |
141
- bundle exec serialbench environment execute config/environments/ci-ruby-${{ matrix.ruby-version }}.yml config/benchmarks/short.yml results/runs/ci-ruby-${{ matrix.ruby-version }}-${{ matrix.platform }}
142
-
143
- - name: Verify benchmark results before upload
144
- run: |
145
- echo "=== Verifying benchmark results ==="
146
- RESULTS_FILE="results/runs/ci-ruby-${{ matrix.ruby-version }}-${{ matrix.platform }}/results.yaml"
147
-
148
- echo "📁 Checking file exists..."
149
- if [ ! -f "$RESULTS_FILE" ]; then
150
- echo "❌ ERROR: results.yaml not found at $RESULTS_FILE"
151
- exit 1
152
- fi
153
-
154
- echo "📊 Checking file size..."
155
- SIZE=$(wc -c < "$RESULTS_FILE" | tr -d ' ')
156
- echo " File size: $SIZE bytes"
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"
157
159
 
158
- if [ "$SIZE" -lt 1000 ]; then
159
- echo "❌ ERROR: results.yaml is suspiciously small ($SIZE bytes)"
160
- echo " Expected at least 1000 bytes for valid benchmark results"
161
- echo "=== File contents ==="
162
- cat "$RESULTS_FILE"
163
- exit 1
164
- 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
165
168
 
166
- 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 }}
167
175
  shell: bash
168
176
 
169
- - name: Validate YAML schema
177
+ - name: Benchmark json
178
+ continue-on-error: true
179
+ shell: bash
180
+ env:
181
+ GITHUB_RUNNER_PLATFORM: ${{ matrix.platform }}
170
182
  run: |
171
- 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"
172
187
 
173
- - name: Upload benchmark results
188
+ - name: Upload json
189
+ if: ${{ !cancelled() }}
174
190
  uses: actions/upload-artifact@v4
175
191
  with:
176
- name: benchmark-results-${{ matrix.platform }}-ruby-${{ matrix.ruby-version }}
177
- 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
178
194
  retention-days: 30
195
+ if-no-files-found: warn
179
196
 
180
- # Aggregate results and deploy to GitHub Pages
181
- deploy-pages:
182
- if: github.ref == 'refs/heads/main'
183
- runs-on: ubuntu-latest
184
- needs: [setup, benchmark]
185
- environment:
186
- name: github-pages
187
- url: ${{ steps.deployment.outputs.page_url }}
188
-
189
- steps:
190
- - name: Checkout repository
191
- uses: actions/checkout@v4
192
-
193
- - name: Set up Ruby
194
- uses: ruby/setup-ruby@v1
195
- with:
196
- ruby-version: '3.3'
197
- 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
198
204
 
199
- - name: Install system dependencies
205
+ - name: Benchmark yaml
206
+ continue-on-error: true
207
+ shell: bash
208
+ env:
209
+ GITHUB_RUNNER_PLATFORM: ${{ matrix.platform }}
200
210
  run: |
201
- sudo apt-get update
202
- sudo apt-get install -y libxml2-dev libxslt1-dev build-essential
203
-
204
- - name: Install gems
205
- 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"
206
215
 
207
- - name: Download all benchmark artifacts
208
- uses: actions/download-artifact@v4
216
+ - name: Upload yaml
217
+ if: ${{ !cancelled() }}
218
+ uses: actions/upload-artifact@v4
209
219
  with:
210
- pattern: benchmark-results-*
211
- path: artifacts/
212
-
213
- - name: List downloaded artifacts structure
214
- run: |
215
- echo "=== Artifacts directory structure ==="
216
- ls -la artifacts/
217
- echo ""
218
- echo "=== Searching for results.yaml files ==="
219
- find artifacts/ -name "results.yaml" -type f
220
- echo ""
221
- echo "=== Directory tree (first 3 levels) ==="
222
- find artifacts/ -maxdepth 3 -type d | sort
223
-
224
- - name: Create resultset
225
- run: |
226
- mkdir -p results/sets
227
- bundle exec serialbench resultset create weekly-benchmark results/sets/weekly-benchmark
228
-
229
- - name: Add all results to resultset
230
- run: |
231
- bundle exec serialbench resultset add-result results/sets/weekly-benchmark artifacts/benchmark-results-*/
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
232
224
 
233
- - name: Generate GitHub Pages site
234
- run: |
235
- bundle exec serialbench resultset build-site results/sets/weekly-benchmark _site
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
236
232
 
237
- - name: Create summary page
233
+ - name: Benchmark toml
234
+ continue-on-error: true
235
+ shell: bash
236
+ env:
237
+ GITHUB_RUNNER_PLATFORM: ${{ matrix.platform }}
238
238
  run: |
239
- mkdir -p _site
240
- cat > _site/README.md << 'EOF'
241
- # Serialbench - Weekly Benchmark Results
242
-
243
- This site contains automated benchmark results for Ruby serialization libraries.
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"
244
243
 
245
- ## Benchmarked Libraries
246
-
247
- - **XML**: REXML, Ox, Nokogiri, Oga, LibXML
248
- - **JSON**: JSON, Oj, RapidJSON, YAJL
249
- - **YAML**: Psych
250
- - **TOML**: TOML-RB, Tomlib, tomlrb
251
-
252
- ## Platforms Tested
253
-
254
- - Ubuntu Latest (Linux x86_64)
255
- - Ubuntu 24.04 (Linux ARM64)
256
- - Ubuntu 22.04 (Linux ARM64)
257
- - macOS 13 (Intel x86_64)
258
- - macOS 15 Intel (Intel x86_64)
259
- - macOS 14 (Apple Silicon ARM64)
260
- - macOS 15 (Apple Silicon ARM64)
261
-
262
- ## Ruby Versions
263
-
264
- - Ruby 3.1, 3.2, 3.3, 3.4
265
-
266
- ## View Results
267
-
268
- Open [index.html](./index.html) to view the interactive dashboard.
269
-
270
- ---
271
-
272
- *Last updated: $(date -u +"%Y-%m-%d %H:%M:%S UTC")*
273
- EOF
274
-
275
- - name: Setup Pages
276
- uses: actions/configure-pages@v4
277
-
278
- - name: Upload to GitHub Pages
279
- uses: actions/upload-pages-artifact@v3
244
+ - name: Upload toml
245
+ if: ${{ !cancelled() }}
246
+ uses: actions/upload-artifact@v4
280
247
  with:
281
- path: _site
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
282
252
 
283
- - name: Deploy to GitHub Pages
284
- id: deployment
285
- 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
286
260
 
287
261
  # Summary job
288
262
  summary:
289
263
  runs-on: ubuntu-latest
290
- needs: [setup, benchmark, deploy-pages]
264
+ needs: [setup, benchmark]
291
265
  if: always()
292
266
  steps:
293
267
  - name: Generate workflow summary
@@ -295,27 +269,19 @@ jobs:
295
269
  echo "## Weekly Benchmark Summary" >> $GITHUB_STEP_SUMMARY
296
270
  echo "" >> $GITHUB_STEP_SUMMARY
297
271
  echo "**Benchmark Status**: ${{ needs.benchmark.result }}" >> $GITHUB_STEP_SUMMARY
298
- 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
299
273
  echo "" >> $GITHUB_STEP_SUMMARY
300
274
  echo "### Platforms Tested" >> $GITHUB_STEP_SUMMARY
301
- echo "- Ubuntu Latest (Linux x86_64)" >> $GITHUB_STEP_SUMMARY
302
- echo "- Ubuntu 24.04 (Linux ARM64)" >> $GITHUB_STEP_SUMMARY
303
- echo "- Ubuntu 22.04 (Linux ARM64)" >> $GITHUB_STEP_SUMMARY
304
- echo "- macOS 13 (Intel x86_64)" >> $GITHUB_STEP_SUMMARY
305
- echo "- macOS 15 Intel (Intel x86_64)" >> $GITHUB_STEP_SUMMARY
306
- echo "- macOS 14 (Apple Silicon ARM64)" >> $GITHUB_STEP_SUMMARY
307
- echo "- macOS 15 (Apple Silicon ARM64)" >> $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
308
279
  echo "" >> $GITHUB_STEP_SUMMARY
309
280
  echo "### Ruby Versions" >> $GITHUB_STEP_SUMMARY
310
- echo "- Ruby 3.1, 3.2, 3.3, 3.4" >> $GITHUB_STEP_SUMMARY
311
- echo "" >> $GITHUB_STEP_SUMMARY
312
- echo "### Serialization Libraries" >> $GITHUB_STEP_SUMMARY
313
- echo "- **XML**: REXML, Ox, Nokogiri, Oga, LibXML" >> $GITHUB_STEP_SUMMARY
314
- echo "- **JSON**: JSON, Oj, RapidJSON, YAJL" >> $GITHUB_STEP_SUMMARY
315
- echo "- **YAML**: Psych" >> $GITHUB_STEP_SUMMARY
316
- echo "- **TOML**: TOML-RB, Tomlib, tomlrb" >> $GITHUB_STEP_SUMMARY
281
+ echo "- Ruby 3.2, 3.3, 3.4, 4.0" >> $GITHUB_STEP_SUMMARY
317
282
  echo "" >> $GITHUB_STEP_SUMMARY
318
283
  if [ "${{ github.ref }}" == "refs/heads/main" ]; then
319
284
  echo "### Results" >> $GITHUB_STEP_SUMMARY
320
- 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
321
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,6 +12,8 @@ unless Gem.win_platform? && RUBY_PLATFORM.include?('aarch64')
12
12
  gem 'libxml-ruby'
13
13
  end
14
14
 
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
+ gem 'benchmark' # Removed from stdlib in Ruby 4.0
15
17
  gem 'base64' # Required for Ruby 3.4+
16
18
  gem 'lutaml-model', '~> 0.7'
17
19
  gem 'octokit'
data/README.adoc CHANGED
@@ -41,6 +41,11 @@ Serialbench is a comprehensive benchmarking suite that evaluates the performance
41
41
  | v3.4
42
42
  | Pure Ruby XML parser with XPath support
43
43
 
44
+ | XML
45
+ | https://github.com/leptris/leptris-ruby[Leptris]
46
+ | v1.1.0
47
+ | FFI binding to libleptris (pure-C XML 1.0, XPath 1.0, SAX)
48
+
44
49
  | XML
45
50
  | https://github.com/ruby/rexml[REXML]
46
51
  | v3.4.1
@@ -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