serialbench 0.1.1 → 0.1.3

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 (100) hide show
  1. checksums.yaml +4 -4
  2. data/.github/workflows/benchmark.yml +273 -220
  3. data/.github/workflows/rake.yml +26 -0
  4. data/.github/workflows/windows-debug.yml +171 -0
  5. data/.gitignore +32 -0
  6. data/.rubocop.yml +1 -0
  7. data/.rubocop_todo.yml +274 -0
  8. data/Gemfile +14 -1
  9. data/README.adoc +292 -1118
  10. data/Rakefile +0 -55
  11. data/config/benchmarks/full.yml +29 -0
  12. data/config/benchmarks/short.yml +26 -0
  13. data/config/environments/asdf-ruby-3.2.yml +8 -0
  14. data/config/environments/asdf-ruby-3.3.yml +8 -0
  15. data/config/environments/docker-ruby-3.0.yml +9 -0
  16. data/config/environments/docker-ruby-3.1.yml +9 -0
  17. data/config/environments/docker-ruby-3.2.yml +9 -0
  18. data/config/environments/docker-ruby-3.3.yml +9 -0
  19. data/config/environments/docker-ruby-3.4.yml +9 -0
  20. data/data/schemas/result.yml +29 -0
  21. data/docker/Dockerfile.alpine +33 -0
  22. data/docker/{Dockerfile.benchmark → Dockerfile.ubuntu} +4 -3
  23. data/docker/README.md +2 -2
  24. data/docs/PLATFORM_VALIDATION_FIX.md +79 -0
  25. data/docs/SYCK_YAML_FIX.md +91 -0
  26. data/docs/WEBSITE_COMPLETION_PLAN.md +440 -0
  27. data/docs/WINDOWS_LIBXML_FIX.md +136 -0
  28. data/docs/WINDOWS_SETUP.md +122 -0
  29. data/exe/serialbench +1 -1
  30. data/lib/serialbench/benchmark_runner.rb +261 -423
  31. data/lib/serialbench/cli/base_cli.rb +51 -0
  32. data/lib/serialbench/cli/benchmark_cli.rb +453 -0
  33. data/lib/serialbench/cli/environment_cli.rb +181 -0
  34. data/lib/serialbench/cli/resultset_cli.rb +261 -0
  35. data/lib/serialbench/cli/ruby_build_cli.rb +225 -0
  36. data/lib/serialbench/cli/validate_cli.rb +88 -0
  37. data/lib/serialbench/cli.rb +61 -600
  38. data/lib/serialbench/config_manager.rb +129 -0
  39. data/lib/serialbench/models/benchmark_config.rb +75 -0
  40. data/lib/serialbench/models/benchmark_result.rb +81 -0
  41. data/lib/serialbench/models/environment_config.rb +72 -0
  42. data/lib/serialbench/models/platform.rb +111 -0
  43. data/lib/serialbench/models/result.rb +80 -0
  44. data/lib/serialbench/models/result_set.rb +79 -0
  45. data/lib/serialbench/models/result_store.rb +108 -0
  46. data/lib/serialbench/models.rb +54 -0
  47. data/lib/serialbench/ruby_build_manager.rb +149 -0
  48. data/lib/serialbench/runners/asdf_runner.rb +296 -0
  49. data/lib/serialbench/runners/base.rb +32 -0
  50. data/lib/serialbench/runners/docker_runner.rb +140 -0
  51. data/lib/serialbench/runners/local_runner.rb +71 -0
  52. data/lib/serialbench/serializers/base_serializer.rb +9 -17
  53. data/lib/serialbench/serializers/json/base_json_serializer.rb +4 -4
  54. data/lib/serialbench/serializers/json/json_serializer.rb +0 -2
  55. data/lib/serialbench/serializers/json/oj_serializer.rb +0 -2
  56. data/lib/serialbench/serializers/json/rapidjson_serializer.rb +1 -1
  57. data/lib/serialbench/serializers/json/yajl_serializer.rb +0 -2
  58. data/lib/serialbench/serializers/toml/base_toml_serializer.rb +5 -5
  59. data/lib/serialbench/serializers/toml/toml_rb_serializer.rb +1 -3
  60. data/lib/serialbench/serializers/toml/tomlib_serializer.rb +1 -3
  61. data/lib/serialbench/serializers/toml/tomlrb_serializer.rb +56 -0
  62. data/lib/serialbench/serializers/xml/base_xml_serializer.rb +4 -9
  63. data/lib/serialbench/serializers/xml/libxml_serializer.rb +4 -10
  64. data/lib/serialbench/serializers/xml/nokogiri_serializer.rb +2 -4
  65. data/lib/serialbench/serializers/xml/oga_serializer.rb +4 -10
  66. data/lib/serialbench/serializers/xml/ox_serializer.rb +2 -4
  67. data/lib/serialbench/serializers/xml/rexml_serializer.rb +3 -5
  68. data/lib/serialbench/serializers/yaml/base_yaml_serializer.rb +5 -1
  69. data/lib/serialbench/serializers/yaml/psych_serializer.rb +1 -1
  70. data/lib/serialbench/serializers/yaml/syck_serializer.rb +60 -23
  71. data/lib/serialbench/serializers.rb +23 -6
  72. data/lib/serialbench/site_generator.rb +283 -0
  73. data/lib/serialbench/templates/assets/css/benchmark_report.css +535 -0
  74. data/lib/serialbench/templates/assets/css/format_based.css +474 -0
  75. data/lib/serialbench/templates/assets/css/themes.css +589 -0
  76. data/lib/serialbench/templates/assets/js/chart_helpers.js +411 -0
  77. data/lib/serialbench/templates/assets/js/dashboard.js +795 -0
  78. data/lib/serialbench/templates/assets/js/navigation.js +142 -0
  79. data/lib/serialbench/templates/base.liquid +49 -0
  80. data/lib/serialbench/templates/format_based.liquid +507 -0
  81. data/lib/serialbench/templates/partials/chart_section.liquid +4 -0
  82. data/lib/serialbench/version.rb +1 -1
  83. data/lib/serialbench/yaml_validator.rb +36 -0
  84. data/lib/serialbench.rb +2 -31
  85. data/serialbench.gemspec +15 -3
  86. metadata +106 -25
  87. data/.github/workflows/ci.yml +0 -74
  88. data/.github/workflows/docker.yml +0 -246
  89. data/config/ci.yml +0 -22
  90. data/config/full.yml +0 -30
  91. data/docker/run-benchmarks.sh +0 -356
  92. data/lib/serialbench/chart_generator.rb +0 -821
  93. data/lib/serialbench/result_formatter.rb +0 -182
  94. data/lib/serialbench/result_merger.rb +0 -1201
  95. data/lib/serialbench/serializers/xml/base_parser.rb +0 -69
  96. data/lib/serialbench/serializers/xml/libxml_parser.rb +0 -98
  97. data/lib/serialbench/serializers/xml/nokogiri_parser.rb +0 -111
  98. data/lib/serialbench/serializers/xml/oga_parser.rb +0 -85
  99. data/lib/serialbench/serializers/xml/ox_parser.rb +0 -64
  100. data/lib/serialbench/serializers/xml/rexml_parser.rb +0 -129
data/README.adoc CHANGED
@@ -13,7 +13,7 @@ Serialbench is a comprehensive benchmarking suite that evaluates the performance
13
13
 
14
14
  **Key Metrics**: Parsing speed, generation speed, memory usage, streaming capabilities, and feature completeness
15
15
 
16
- **Docker Support**: Multi-Ruby version benchmarking with automated result aggregation and GitHub Pages generation
16
+ **Multi-Environment Support**: Docker and ASDF-based multi-Ruby version benchmarking with automated result aggregation and HTML site generation
17
17
 
18
18
  == Supported serialization libraries
19
19
 
@@ -80,1121 +80,402 @@ Serialbench is a comprehensive benchmarking suite that evaluates the performance
80
80
  | https://github.com/emancu/toml-rb[TOML-RB]
81
81
  | v2.2.0
82
82
  | Pure Ruby TOML parser
83
- |===
84
-
85
- == Benchmark report JSON format
86
-
87
- === Single Ruby version results
88
-
89
- The benchmark results are saved as JSON files with the following structure:
90
-
91
- [source,json]
92
- ----
93
- {
94
- "environment": {
95
- "ruby_version": "3.3.8",
96
- "ruby_platform": "aarch64-linux",
97
- "serializer_versions": {
98
- "rexml": "3.4.1",
99
- "ox": "2.14.23",
100
- "nokogiri": "1.18.8",
101
- "oga": "3.4",
102
- "libxml": "4.1.2",
103
- "json": "2.12.2",
104
- "oj": "3.16.11",
105
- "yajl": "1.4.3",
106
- "psych": "5.1.2",
107
- "syck": "1.5.1.1",
108
- "toml-rb": "2.2.0",
109
- "tomlib": "0.7.3"
110
- },
111
- "timestamp": "2025-06-07T09:00:25+00:00"
112
- },
113
- "parsing": {
114
- "small": {
115
- "xml": {
116
- "rexml": {
117
- "time_per_iterations": 0.002514416000053643,
118
- "time_per_iteration": 0.00012572080000268216,
119
- "iterations_per_second": 7954.133285650949,
120
- "iterations_count": 20
121
- },
122
- "ox": {
123
- "time_per_iterations": 0.00005258399994545471,
124
- "time_per_iteration": 0.0000026291999972727353,
125
- "iterations_per_second": 380343.83121759404,
126
- "iterations_count": 20
127
- }
128
- },
129
- "json": {
130
- "json": {
131
- "time_per_iterations": 0.000029707999942729657,
132
- "time_per_iteration": 0.000001485399997136483,
133
- "iterations_per_second": 673219.3361571126,
134
- "iterations_count": 20
135
- },
136
- "oj": {
137
- "time_per_iterations": 0.00003158300000905001,
138
- "time_per_iteration": 0.0000015791500004525006,
139
- "iterations_per_second": 633252.0658034089,
140
- "iterations_count": 20
141
- }
142
- }
143
- },
144
- "medium": {
145
- "xml": { /* ... */ },
146
- "json": { /* ... */ }
147
- },
148
- "large": {
149
- "xml": { /* ... */ },
150
- "json": { /* ... */ }
151
- }
152
- },
153
- "ruby_version": "3.3.8",
154
- "ruby_platform": "aarch64-linux",
155
- "timestamp": "2025-06-07T09:01:02+00:00"
156
- }
157
- ----
158
-
159
- === Multi-Ruby version merged results
160
-
161
- When results from multiple Ruby versions are merged, the structure becomes:
162
-
163
- [source,json]
164
- ----
165
- {
166
- "environments": {
167
- "3_3_8_aarch64_linux": {
168
- "ruby_version": "3.3.8",
169
- "ruby_platform": "aarch64-linux",
170
- "source_file": "docker-results/ruby-3.3/data/results.json",
171
- "timestamp": "2025-06-07T09:01:02+00:00",
172
- "environment": {
173
- "ruby_version": "3.3.8",
174
- "ruby_platform": "aarch64-linux",
175
- "serializer_versions": { /* ... */ },
176
- "timestamp": "2025-06-07T09:00:25+00:00"
177
- }
178
- },
179
- "3_4_4_aarch64_linux": {
180
- "ruby_version": "3.4.4",
181
- "ruby_platform": "aarch64-linux",
182
- /* ... */
183
- }
184
- },
185
- "combined_results": {
186
- "parsing": {
187
- "small": {
188
- "xml": {
189
- "rexml": {
190
- "3_3_8_aarch64_linux": {
191
- "time_per_iterations": 0.002514416000053643,
192
- "time_per_iteration": 0.00012572080000268216,
193
- "iterations_per_second": 7954.133285650949,
194
- "iterations_count": 20
195
- },
196
- "3_4_4_aarch64_linux": {
197
- "time_per_iterations": 0.0025308329999234047,
198
- "time_per_iteration": 0.00012654164999617023,
199
- "iterations_per_second": 7902.536437846866,
200
- "iterations_count": 20
201
- }
202
- }
203
- }
204
- }
205
- }
206
- },
207
- "metadata": {
208
- "merged_at": "2025-06-07T17:01:48+08:00",
209
- "ruby_versions": ["3.3.8", "3.4.4"],
210
- "platforms": ["aarch64-linux"]
211
- }
212
- }
213
- ----
214
-
215
- === JSON schema specification
216
-
217
- The benchmark results follow this schema:
218
-
219
- [source,json]
220
- ----
221
- {
222
- "$schema": "http://json-schema.org/draft-07/schema#",
223
- "title": "Serialbench Results",
224
- "type": "object",
225
- "properties": {
226
- "environment": {
227
- "type": "object",
228
- "properties": {
229
- "ruby_version": { "type": "string" },
230
- "ruby_platform": { "type": "string" },
231
- "serializer_versions": {
232
- "type": "object",
233
- "additionalProperties": { "type": "string" }
234
- },
235
- "timestamp": { "type": "string", "format": "date-time" }
236
- },
237
- "required": ["ruby_version", "ruby_platform", "serializer_versions", "timestamp"]
238
- },
239
- "parsing": {
240
- "type": "object",
241
- "properties": {
242
- "small": { "$ref": "#/definitions/sizeResults" },
243
- "medium": { "$ref": "#/definitions/sizeResults" },
244
- "large": { "$ref": "#/definitions/sizeResults" }
245
- }
246
- },
247
- "ruby_version": { "type": "string" },
248
- "ruby_platform": { "type": "string" },
249
- "timestamp": { "type": "string", "format": "date-time" }
250
- },
251
- "definitions": {
252
- "sizeResults": {
253
- "type": "object",
254
- "properties": {
255
- "xml": { "$ref": "#/definitions/formatResults" },
256
- "json": { "$ref": "#/definitions/formatResults" },
257
- "yaml": { "$ref": "#/definitions/formatResults" },
258
- "toml": { "$ref": "#/definitions/formatResults" }
259
- }
260
- },
261
- "formatResults": {
262
- "type": "object",
263
- "additionalProperties": {
264
- "$ref": "#/definitions/serializerResults"
265
- }
266
- },
267
- "serializerResults": {
268
- "type": "object",
269
- "properties": {
270
- "time_per_iterations": { "type": "number" },
271
- "time_per_iteration": { "type": "number" },
272
- "iterations_per_second": { "type": "number" },
273
- "iterations_count": { "type": "integer" }
274
- },
275
- "required": ["time_per_iterations", "time_per_iteration", "iterations_per_second", "iterations_count"]
276
- }
277
- }
278
- }
279
- ----
280
-
281
- == Installation
282
-
283
- Add this line to your application's Gemfile:
284
-
285
- [source,ruby]
286
- ----
287
- gem 'serialbench'
288
- ----
289
-
290
- And then execute:
291
-
292
- [source]
293
- ----
294
- $ bundle install
295
- ----
296
-
297
- Or install it yourself as:
298
-
299
- [source]
300
- ----
301
- $ gem install serialbench
302
- ----
303
-
304
- === XML library dependencies
305
-
306
- To run benchmarks for all supported XML libraries, install the following gems:
307
83
 
84
+ | TOML
85
+ | https://github.com/fbernier/tomlrb[tomlrb]
86
+ | v2.0.3
87
+ | A Racc based TOML Ruby parser (Only supports parsing, no support for dumping/writing.)
308
88
 
309
- [source]
310
- ----
311
- # Core XML libraries
312
- $ gem install ox nokogiri libxml-ruby oga
89
+ |===
313
90
 
314
- # Additional format libraries (for comparison)
315
- $ gem install oj toml-rb
316
91
 
317
- # Memory profiling support
318
- $ gem install memory_profiler
319
- ----
92
+ == Data formats and schema
320
93
 
94
+ Serialbench generates structured YAML output for benchmark results, with
95
+ different formats for single-environment and multi-environment runs.
321
96
 
322
- NOTE: REXML, JSON, and Psych (YAML) are included with Ruby and require no additional installation.
97
+ The data formats include:
323
98
 
324
- === Library-specific installation notes
99
+ * **Single benchmark results**: Individual benchmark run output
100
+ * **Result set data structure**: Multi-platform benchmark aggregation
101
+ * **JSON schema specification**: Complete schema validation rules
102
+ * **Configuration file formats**: Docker and ASDF configuration examples
325
103
 
326
- ==== Ox
104
+ == Prerequisites
327
105
 
328
- High-performance C extension requiring compilation:
106
+ === System requirements
329
107
 
330
- [source]
331
- ----
332
- $ gem install ox
333
- ----
108
+ * **Ruby**: 3.0 or later (3.3+ recommended for best performance)
109
+ * **Operating system**: Linux, macOS, or Windows
110
+ * **Architecture**: x86_64 or ARM64
334
111
 
335
- ==== Nokogiri
112
+ === Library dependencies
336
113
 
337
- May require system dependencies on some platforms:
114
+ **System dependencies** (required for some native extensions):
338
115
 
339
- [source]
116
+ [source,bash]
340
117
  ----
341
118
  # macOS with Homebrew
342
119
  $ brew install libxml2 libxslt
343
- $ gem install nokogiri
344
-
345
- # Ubuntu/Debian
346
- $ sudo apt-get install libxml2-dev libxslt1-dev
347
- $ gem install nokogiri
348
- ----
349
-
350
- ==== LibXML
351
-
352
- Ruby bindings for libxml2:
353
-
354
- [source]
355
- ----
356
- # macOS with Homebrew
357
- $ brew install libxml2
358
- $ gem install libxml-ruby
359
120
 
360
121
  # Ubuntu/Debian
361
- $ sudo apt-get install libxml2-dev
362
- $ gem install libxml-ruby
363
- ----
364
-
365
- ==== Oga
366
-
367
- Pure Ruby implementation with no system dependencies:
122
+ $ sudo apt-get install libxml2-dev libxslt1-dev build-essential
368
123
 
369
- [source]
370
- ----
371
- $ gem install oga
124
+ # CentOS/RHEL/Fedora
125
+ $ sudo yum install libxml2-devel libxslt-devel gcc gcc-c++
372
126
  ----
373
127
 
374
- == Docker containers and cross-platform benchmarking
128
+ === GitHub API token (optional but recommended)
375
129
 
376
- Serialbench provides pre-built Docker containers and supports cross-platform benchmarking on Windows, macOS, and Linux. Our containers are automatically built and published to GitHub Container Registry for easy access.
130
+ Serialbench fetches Ruby build definitions from the GitHub API. While this works
131
+ without authentication, GitHub imposes strict rate limits on unauthenticated
132
+ requests (60 requests per hour). For better reliability, especially in CI/CD
133
+ environments or when running multiple benchmarks, set the `GITHUB_TOKEN`
134
+ environment variable.
377
135
 
378
- === Published Docker containers
136
+ **Rate limits:**
379
137
 
380
- We publish multi-architecture Docker containers for all supported Ruby versions:
138
+ * **Without token**: 60 requests per hour
139
+ * **With token**: 1,000 requests per hour
381
140
 
382
- **Registry**: `ghcr.io/metanorma/serialbench`
383
-
384
- **Available tags**:
385
- * `ghcr.io/metanorma/serialbench:main-ruby-3.1` - Ruby 3.1 (linux/amd64, linux/arm64)
386
- * `ghcr.io/metanorma/serialbench:main-ruby-3.2` - Ruby 3.2 (linux/amd64, linux/arm64)
387
- * `ghcr.io/metanorma/serialbench:main-ruby-3.3` - Ruby 3.3 (linux/amd64, linux/arm64)
388
- * `ghcr.io/metanorma/serialbench:main-ruby-3.4` - Ruby 3.4 (linux/amd64, linux/arm64)
389
-
390
- **Container features**:
391
- * All serialization libraries pre-installed (XML, JSON, YAML, TOML)
392
- * Multi-architecture support (Intel x64 and ARM64)
393
- * Optimized for CI/CD and local development
394
- * Automatic updates on code changes
395
-
396
- === Running benchmarks on your computer
397
-
398
- ==== Windows (PowerShell/Command Prompt)
399
-
400
- [source,powershell]
401
- ----
402
- # Pull and run latest Ruby 3.3 container
403
- docker pull ghcr.io/metanorma/serialbench:main-ruby-3.3
404
-
405
- # Create results directory
406
- mkdir results
407
-
408
- # Run benchmarks with volume mounting
409
- docker run --rm -v ${PWD}/results:/app/results ghcr.io/metanorma/serialbench:main-ruby-3.3
410
-
411
- # View results
412
- dir results
413
- ----
414
-
415
- ==== macOS (Terminal)
141
+ **Setting the token:**
416
142
 
417
143
  [source,bash]
418
144
  ----
419
- # Pull and run latest Ruby 3.3 container
420
- docker pull ghcr.io/metanorma/serialbench:main-ruby-3.3
421
-
422
- # Create results directory
423
- mkdir -p results
424
-
425
- # Run benchmarks with volume mounting
426
- docker run --rm -v $(pwd)/results:/app/results ghcr.io/metanorma/serialbench:main-ruby-3.3
427
-
428
- # View results
429
- ls -la results/
430
- ----
431
-
432
- ==== Ubuntu/Linux (Terminal)
433
-
434
- [source,bash]
435
- ----
436
- # Pull and run latest Ruby 3.3 container
437
- docker pull ghcr.io/metanorma/serialbench:main-ruby-3.3
438
-
439
- # Create results directory
440
- mkdir -p results
441
-
442
- # Run benchmarks with volume mounting
443
- docker run --rm -v $(pwd)/results:/app/results ghcr.io/metanorma/serialbench:main-ruby-3.3
145
+ # For local usage
146
+ export GITHUB_TOKEN=ghp_your_token_here
444
147
 
445
- # View results
446
- ls -la results/
148
+ # For GitHub Actions (automatic)
149
+ # GitHub Actions automatically provides ${{ secrets.GITHUB_TOKEN }}
150
+ # No manual configuration needed in workflows
447
151
  ----
448
152
 
449
- === Multi-Ruby version comparison
153
+ **Creating a token:**
450
154
 
451
- Run benchmarks across all supported Ruby versions:
155
+ . Go to https://github.com/settings/tokens
156
+ . Click "Generate new token (classic)"
157
+ . Select scope: `public_repo` (for accessing public repositories)
158
+ . Copy the generated token
159
+ . Store it securely in your environment
452
160
 
453
- ==== Windows (PowerShell)
161
+ NOTE: The token is optional. Serialbench will work without it but may hit rate
162
+ limits when updating Ruby build definitions frequently.
454
163
 
455
- [source,powershell]
456
- ----
457
- # Create results directories
458
- $versions = @("3.1", "3.2", "3.3", "3.4")
459
- foreach ($version in $versions) {
460
- mkdir "results-ruby-$version" -Force
461
- docker pull "ghcr.io/metanorma/serialbench:main-ruby-$version"
462
- docker run --rm -v "${PWD}/results-ruby-${version}:/app/results" "ghcr.io/metanorma/serialbench:main-ruby-$version"
463
- }
464
-
465
- # View all results
466
- dir results-ruby-*
467
- ----
468
-
469
- ==== macOS/Linux (Bash)
470
-
471
- [source,bash]
472
- ----
473
- # Run benchmarks for all Ruby versions
474
- for version in 3.1 3.2 3.3 3.4; do
475
- echo "Running benchmarks for Ruby $version..."
476
- mkdir -p "results-ruby-$version"
477
- docker pull "ghcr.io/metanorma/serialbench:main-ruby-$version"
478
- docker run --rm \
479
- -v "$(pwd)/results-ruby-$version:/app/results" \
480
- "ghcr.io/metanorma/serialbench:main-ruby-$version"
481
- done
482
-
483
- # View all results
484
- ls -la results-ruby-*/
485
- ----
486
-
487
- === Custom benchmark configuration
164
+ == Installation
488
165
 
489
- Run benchmarks with custom parameters:
166
+ Add this line to your application's Gemfile:
490
167
 
491
- [source,bash]
168
+ [source,ruby]
492
169
  ----
493
- # Run specific formats only
494
- docker run --rm \
495
- -v $(pwd)/results:/app/results \
496
- ghcr.io/metanorma/serialbench:main-ruby-3.3 \
497
- bundle exec serialbench benchmark --formats xml json --iterations 10
498
-
499
- # Run with memory profiling
500
- docker run --rm \
501
- -v $(pwd)/results:/app/results \
502
- ghcr.io/metanorma/serialbench:main-ruby-3.3 \
503
- bundle exec serialbench benchmark --memory-profiling
504
-
505
- # List available serializers
506
- docker run --rm ghcr.io/metanorma/serialbench:main-ruby-3.3 \
507
- bundle exec serialbench list
170
+ gem 'serialbench'
508
171
  ----
509
172
 
510
- === Quick start with Docker
511
-
512
- ==== Prerequisites
513
-
514
- * Docker installed and running
515
- * Command line access (PowerShell, Terminal, or Bash)
516
-
517
- ==== Running multi-Ruby benchmarks
173
+ And then execute:
518
174
 
519
175
  [source]
520
176
  ----
521
- # From the project root directory (if you have the source)
522
- $ ./docker/run-benchmarks.sh
523
-
524
- # Or using published containers directly
525
- $ docker pull ghcr.io/metanorma/serialbench:main-ruby-3.3
526
- $ docker run --rm -v $(pwd)/results:/app/results ghcr.io/metanorma/serialbench:main-ruby-3.3
177
+ $ bundle install
527
178
  ----
528
179
 
529
- This will:
530
-
531
- . **Pull pre-built containers** from GitHub Container Registry
532
- . **Run comprehensive benchmarks** in isolated environments
533
- . **Generate detailed reports** with performance comparisons
534
- . **Output results** to your local `results/` directory
535
-
536
- ==== Results structure
537
-
538
- Results are organized in `docker-results/`:
180
+ Or install it yourself as:
539
181
 
540
182
  [source]
541
183
  ----
542
- docker-results/
543
- ├── ruby-3.0/ # Ruby 3.0 individual results
544
- │ ├── benchmark.log # Execution log
545
- │ ├── data/
546
- │ │ ├── results.json # Raw benchmark data
547
- │ │ └── results.yaml # YAML format results
548
- │ ├── reports/
549
- │ │ └── benchmark_report.html
550
- │ └── assets/
551
- ├── ruby-3.1/ # Ruby 3.1 individual results
552
- ├── ruby-3.2/ # Ruby 3.2 individual results
553
- ├── ruby-3.3/ # Ruby 3.3 individual results
554
- ├── ruby-3.4/ # Ruby 3.4 individual results
555
- ├── merged/ # Aggregated cross-version results
556
- │ └── merged_results.json # Combined performance data
557
- └── docs/ # GitHub Pages ready output
558
- ├── index.html # Interactive comparison report
559
- ├── styles.css # Report styling
560
- └── merged_results.json # Data for interactive charts
184
+ $ gem install serialbench
561
185
  ----
562
186
 
563
- === Manual Docker usage
564
187
 
565
- ==== Build image for specific Ruby version
188
+ == Command line interface
566
189
 
567
- [source]
568
- ----
569
- $ docker build \
570
- --build-arg RUBY_VERSION=3.3 \
571
- -t serialbench:ruby-3.3 \
572
- -f docker/Dockerfile.benchmark \
573
- .
574
- ----
190
+ Serialbench provides a comprehensive Thor-based CLI with four main subcommands
191
+ for managing environments, benchmarks, result sets, and Ruby builds.
575
192
 
576
- ==== Run benchmarks in container
193
+ === Main Commands Overview
577
194
 
578
- [source]
195
+ [source,sh]
579
196
  ----
580
- # Create results directory
581
- $ mkdir -p results
582
-
583
- # Run benchmarks with volume mounting
584
- $ docker run \
585
- --rm \
586
- -v $(pwd)/results:/app/results \
587
- serialbench:ruby-3.3
588
- ----
589
-
590
- ==== Custom configuration
197
+ $ serialbench
198
+ Serialbench - Benchmarking Framework for Ruby Serialization Libraries
591
199
 
592
- [source]
593
- ----
594
- # Use custom config file
595
- $ docker run \
596
- --rm \
597
- -v $(pwd)/results:/app/results \
598
- -v $(pwd)/config:/app/config \
599
- serialbench:ruby-3.3 \
600
- bundle exec serialbench benchmark --config config/ci.yml
601
- ----
200
+ USAGE:
201
+ serialbench COMMAND [SUBCOMMAND] [OPTIONS]
602
202
 
603
- === Supported Ruby versions
203
+ COMMANDS:
204
+ environment Manage benchmark environments (Docker, ASDF, Local)
205
+ benchmark Manage individual benchmark runs
206
+ resultset Manage benchmark resultsets (collections of runs)
207
+ ruby-build Manage Ruby-Build definitions for validation
208
+ version Show version information
209
+ help Show this help message
604
210
 
605
- The Docker setup supports the following Ruby versions:
211
+ EXAMPLES:
212
+ # Create a Docker environment
213
+ serialbench environment new docker-test docker
606
214
 
607
- * **Ruby 3.0** - Stable release with good performance baseline
608
- * **Ruby 3.1** - Improved performance and new features
609
- * **Ruby 3.2** - Enhanced YJIT and memory optimizations
610
- * **Ruby 3.3** - Latest stable with performance improvements
611
- * **Ruby 3.4** - Current development version
612
-
613
- Each version includes all supported serialization libraries:
614
-
615
- * **XML**: REXML (built-in), Ox, Nokogiri, Oga, LibXML
616
- * **JSON**: JSON (built-in), Oj, YAJL
617
- * **YAML**: Psych (built-in), Syck
618
- * **TOML**: TOML-RB, Tomlib
619
-
620
- === Environment variables
621
-
622
- The Docker images support these environment variables:
623
-
624
- * `BUNDLE_PATH` - Bundle installation path
625
- * `BUNDLE_BIN` - Bundle binary path
626
- * `PATH` - System PATH including bundle binaries
627
- * `RUBY_VERSION` - Ruby version for build-time configuration
628
-
629
- === Result aggregation and GitHub Pages
630
-
631
- ==== Merging multi-version results
632
-
633
- The Docker workflow automatically merges results from all Ruby versions:
634
-
635
- [source]
636
- ----
637
- # Manual result merging
638
- $ serialbench merge_results \
639
- docker-results/ruby-3.0 \
640
- docker-results/ruby-3.1 \
641
- docker-results/ruby-3.2 \
642
- docker-results/ruby-3.3 \
643
- docker-results/ruby-3.4 \
644
- docker-results/merged
645
- ----
215
+ # Run multi-environment benchmarks
216
+ serialbench environment multi-execute asdf --config=serialbench-asdf.yml
217
+ serialbench environment multi-execute docker --config=serialbench-docker.yml
646
218
 
647
- ==== GitHub Pages generation
219
+ # Create and execute a benchmark
220
+ serialbench benchmark create my-benchmark
221
+ serialbench benchmark execute my-benchmark.yml
648
222
 
649
- Generate interactive HTML reports ready for GitHub Pages deployment:
223
+ # Create a result set for comparison
224
+ serialbench resultset create comparison-set
225
+ serialbench resultset add-result comparison-set results/my-benchmark
650
226
 
651
- [source]
227
+ # Generate static sites
228
+ serialbench benchmark build-site results/my-benchmark
229
+ serialbench resultset build-site resultsets/comparison-set
652
230
  ----
653
- # Generate GitHub Pages from multi-version results
654
- $ serialbench github_pages \
655
- docker-results/ruby-3.0 \
656
- docker-results/ruby-3.1 \
657
- docker-results/ruby-3.2 \
658
- docker-results/ruby-3.3 \
659
- docker-results/ruby-3.4 \
660
- docker-results/docs
661
- ----
662
-
663
- The generated GitHub Pages include:
664
231
 
665
- * **Interactive Performance Charts**: Compare serializers across Ruby versions
666
- * **Multi-Version Analysis**: See how performance changes between Ruby releases
667
- * **Environment Details**: Ruby versions, platforms, and library versions
668
- * **Responsive Design**: Works on desktop and mobile devices
669
- * **Direct Deployment**: Ready for GitHub Pages, Netlify, or any static hosting
232
+ === Environment management
670
233
 
671
- ==== Deploying to GitHub Pages
234
+ The `environment` subcommand manages environment configurations and executes
235
+ benchmarks across different Ruby environments.
672
236
 
673
- . **Commit the generated files**:
674
- +
675
237
  [source]
676
238
  ----
677
- $ git add docker-results/docs/
678
- $ git commit -m "Add multi-Ruby benchmark results"
679
- $ git push origin main
239
+ $ serialbench environment help
240
+ Commands:
241
+ serialbench environment execute ENVIRONMENT_CONFIG BENCHMARK_CONFIG RESULT_PATH # Execute benchmark in environment
242
+ serialbench environment help [COMMAND] # Describe subcommands or one specific subcommand
243
+ serialbench environment new NAME KIND RUBY_BUILD_TAG # Create a new environment configuration
244
+ serialbench environment prepare ENVIRONMENT_CONFIG # Prepare environment for benchmarking
680
245
  ----
681
246
 
682
- . **Enable GitHub Pages** in repository settings:
683
- .. Go to Settings → Pages
684
- .. Set source to "Deploy from a branch"
685
- .. Select branch containing the `docs/` folder
686
- .. Set folder to `/docker-results/docs`
687
-
688
- . **Access your results** at: `https://yourusername.github.io/yourrepo/`
689
247
 
690
- === Troubleshooting Docker issues
248
+ === Benchmark management
691
249
 
692
- ==== Build failures
693
-
694
- Check build logs for specific Ruby versions:
250
+ The `benchmark` subcommand handles individual benchmark runs and site generation.
695
251
 
696
252
  [source]
697
253
  ----
698
- $ cat docker-results/build-ruby-3.3.log
254
+ $ serialbench benchmark help
255
+ Commands:
256
+ serialbench benchmark _docker_execute ENVIRONMENT_CONFIG_PATH BENCHMARK_CONFIG_PATH # (Private) Execute a benchmark run
257
+ serialbench benchmark build-site RUN_PATH [OUTPUT_DIR] # Generate HTML site for a run
258
+ serialbench benchmark create [NAME] # Generate a run configuration file
259
+ serialbench benchmark execute ENVIRONMENT_CONFIG_PATH BENCHMARK_CONFIG_PATH # Execute a benchmark run
260
+ serialbench benchmark help [COMMAND] # Describe subcommands or one specific subcommand
261
+ serialbench benchmark list # List all available runs
699
262
  ----
700
263
 
701
- Common build issues:
264
+ The `_docker_execute` command is a private command used internally by the
265
+ `execute` command to run benchmarks in Docker environments.
702
266
 
703
- * **Missing system dependencies**: Ensure libxml2-dev and libxslt1-dev are available
704
- * **Network timeouts**: Retry the build or use a different network
705
- * **Disk space**: Ensure sufficient disk space for multiple Ruby images
706
267
 
707
- ==== Runtime failures
268
+ === Result set management
708
269
 
709
- Check benchmark execution logs:
270
+ The `resultset` subcommand manages collections of benchmark runs for comparison analysis.
710
271
 
711
272
  [source]
712
273
  ----
713
- $ cat docker-results/ruby-3.3/benchmark.log
274
+ $ serialbench resultset help
275
+ Commands:
276
+ serialbench resultset add-result RESULT_PATH RESULTSET_PATH # Add a run to a resultset
277
+ serialbench resultset build-site RESULTSET_PATH [OUTPUT_DIR] # Generate HTML site for a resultset
278
+ serialbench resultset create NAME PATH # Create a new resultset
279
+ serialbench resultset help [COMMAND] # Describe subcommands or one specific subcommand
280
+ serialbench resultset list # List all available resultsets
281
+ serialbench resultset remove-result RESULTSET_PATH RESULT_PATH # Remove a run from a resultset
714
282
  ----
715
283
 
716
- Common runtime issues:
717
284
 
718
- * **Memory constraints**: Increase Docker memory allocation
719
- * **Timeout issues**: Some benchmarks may take longer on slower systems
720
- * **Permission errors**: Ensure proper volume mounting permissions
285
+ === ruby-build management
721
286
 
722
- ==== Docker system issues
287
+ The `ruby-build` subcommand manages Ruby build definitions and version information.
723
288
 
724
- Verify Docker is running properly:
289
+ Serialbench uses ruby-build definitions of Ruby interpreter types and versions
290
+ for identification.
725
291
 
726
292
  [source]
727
293
  ----
728
- $ docker info
729
- $ docker system df # Check disk usage
730
- $ docker system prune # Clean up unused resources
731
- ----
732
-
733
- Clean up Serialbench Docker resources:
734
-
735
- [source]
294
+ $ serialbench ruby-build help
295
+ Commands:
296
+ serialbench ruby_build cache-info # Show information about the Ruby-Build definitions cache
297
+ serialbench ruby_build help [COMMAND] # Describe subcommands or one specific subcommand
298
+ serialbench ruby_build list [FILTER] # List available Ruby-Build definitions
299
+ serialbench ruby_build show TAG # Show details for a specific Ruby-Build definition
300
+ serialbench ruby_build suggest # Suggest Ruby-Build tag for current Ruby version
301
+ serialbench ruby_build update # Update Ruby-Build definitions from GitHub
302
+ serialbench ruby_build validate TAG # Validate a Ruby-Build tag
736
303
  ----
737
- # Remove all Serialbench images
738
- $ docker rmi $(docker images serialbench -q)
739
304
 
740
- # Remove all containers
741
- $ docker container prune
742
- ----
743
305
 
744
- === Customization options
306
+ == Workflow examples
745
307
 
746
- ==== Adding Ruby versions
308
+ === Docker-based testing
747
309
 
748
- Edit the `RUBY_VERSIONS` array in `docker/run-benchmarks.sh`:
310
+ NOTE: This works.
749
311
 
750
312
  [source,bash]
751
313
  ----
752
- RUBY_VERSIONS=("3.0" "3.1" "3.2" "3.3" "3.4" "head")
753
- ----
314
+ # 1. Prepare Docker environment
315
+ $ bundle exec serialbench environment prepare config/environments/docker-ruby-3.1.yml
754
316
 
755
- ==== Custom benchmark configuration
317
+ # 2. Run benchmark
318
+ $ bundle exec serialbench environment execute config/environments/docker-ruby-3.1.yml config/benchmarks/short.yml results/runs/docker-ruby-3.1-results
756
319
 
757
- Create custom config files in the `config/` directory:
320
+ # 3. Create a resultset
321
+ $ bundle exec serialbench resultset create docker-comparison results/sets/docker-comparison
758
322
 
759
- [source,yaml]
760
- ----
761
- # config/custom.yml
762
- formats:
763
- - xml
764
- - json
765
- iterations: 50
766
- warmup: 5
767
- data_sizes:
768
- - small
769
- - medium
770
- ----
771
-
772
- Reference the custom config in the run script:
323
+ # 3a. (Optional) Build the site from the result if you want to visualize results
324
+ $ bundle exec serialbench benchmark build-site results/runs/docker-ruby-3.1-results/ --output_dir=_site_result
773
325
 
774
- [source,bash]
775
- ----
776
- # In docker/run-benchmarks.sh
777
- CONFIG_FILE="config/custom.yml"
778
- ----
326
+ # 4. Add the result to the resultset
327
+ $ bundle exec serialbench resultset add-result results/sets/docker-comparison/ results/runs/docker-ruby-3.1-results/
779
328
 
780
- ==== Output directory customization
329
+ # 5. Build the site from the resultset
330
+ $ bundle exec serialbench resultset build-site results/sets/docker-comparison/
781
331
 
782
- Change the output directory in the run script:
783
-
784
- [source,bash]
785
- ----
786
- # In docker/run-benchmarks.sh
787
- OUTPUT_DIR="my-benchmark-results"
332
+ # 6. Open the generated site
333
+ $ open _site/index.html
788
334
  ----
789
335
 
790
- === Integration with CI/CD
791
-
792
- ==== GitHub Actions integration
793
-
794
- The Docker setup integrates seamlessly with GitHub Actions:
795
-
796
- [source,yaml]
797
- ----
798
- # .github/workflows/benchmark.yml
799
- name: Multi-Ruby Benchmarks
800
-
801
- on:
802
- schedule:
803
- - cron: '0 2 * * 0' # Weekly on Sunday at 2 AM
804
- workflow_dispatch:
805
-
806
- permissions:
807
- contents: read
808
- pages: write
809
- id-token: write
810
-
811
- concurrency:
812
- group: "pages"
813
- cancel-in-progress: false
814
-
815
- jobs:
816
- benchmark:
817
- runs-on: ubuntu-latest
818
- steps:
819
- - name: Checkout repository
820
- uses: actions/checkout@v4
821
-
822
- - name: Setup Docker Buildx
823
- uses: docker/setup-buildx-action@v3
824
-
825
- - name: Run Docker Benchmarks
826
- run: ./docker/run-benchmarks.sh
827
-
828
- - name: Upload Results
829
- uses: actions/upload-artifact@v4
830
- with:
831
- name: benchmark-results
832
- path: docker-results/
833
-
834
- - name: Setup Pages
835
- uses: actions/configure-pages@v4
836
-
837
- - name: Upload Pages artifact
838
- uses: actions/upload-pages-artifact@v3
839
- with:
840
- path: ./docker-results/docs
841
-
842
- deploy:
843
- environment:
844
- name: github-pages
845
- url: ${{ steps.deployment.outputs.page_url }}
846
- runs-on: ubuntu-latest
847
- needs: benchmark
848
- steps:
849
- - name: Deploy to GitHub Pages
850
- id: deployment
851
- uses: actions/deploy-pages@v4
852
- ----
853
-
854
- ==== Performance considerations
855
-
856
- * **Parallel builds**: Docker builds can run in parallel for faster execution
857
- * **Build caching**: Subsequent runs use cached layers for faster builds
858
- * **Memory profiling**: Enabled by default but can be disabled for faster runs
859
- * **Result compression**: Large result files can be compressed for storage
860
-
861
- === Security considerations
862
-
863
- * **Containers run with minimal privileges**: No root access required
864
- * **No network access during benchmarks**: Isolated execution environment
865
- * **Volume mounting**: Results written only to specified mounted volumes
866
- * **Image scanning**: Regular security updates for base Ruby images
867
-
868
- == Usage
869
-
870
- === Command line interface
871
-
872
- ==== Basic usage
873
-
874
- Run benchmarks for all available formats:
875
-
876
- [source]
877
- ----
878
- $ serialbench benchmark
879
- ----
336
+ === ASDF-based testing
880
337
 
881
- List all available serializers:
338
+ WARNING: THIS IS NOT YET WORKING.
882
339
 
883
- [source]
884
- ----
885
- $ serialbench list
886
- ----
887
-
888
- Show help information:
889
-
890
- [source]
891
- ----
892
- $ serialbench help
893
- $ serialbench help benchmark
894
- ----
895
-
896
- Show version:
897
-
898
- [source]
899
- ----
900
- $ serialbench version
901
- ----
902
-
903
- ==== Format-specific benchmarks
904
-
905
- ===== XML benchmarks
906
-
907
- Run all XML library benchmarks:
908
-
909
- [source]
910
- ----
911
- $ serialbench benchmark --formats xml
912
- ----
913
-
914
- Test specific XML libraries:
915
-
916
- [source]
917
- ----
918
- $ serialbench benchmark --formats xml --parsers ox,nokogiri
919
- $ serialbench benchmark --formats xml --parsers rexml,oga,libxml
340
+ [source,bash]
920
341
  ----
342
+ # 1. Validate configuration
343
+ $ bundle exec serialbench benchmark validate serialbench-asdf.yml
921
344
 
922
- XML-only parsing performance:
345
+ # 2. Prepare Ruby environments
346
+ $ bundle exec serialbench benchmark prepare asdf --config=serialbench-asdf.yml
923
347
 
924
- [source]
925
- ----
926
- $ serialbench benchmark --formats xml --parsing-only
927
- ----
348
+ # 3. Run benchmarks across all Ruby versions
349
+ $ bundle exec serialbench benchmark execute asdf --config=serialbench-asdf.yml
928
350
 
929
- XML generation benchmarks:
930
-
931
- [source]
932
- ----
933
- $ serialbench benchmark --formats xml --generation-only
351
+ # 4. Results are automatically merged and dashboard generated
352
+ $ open asdf-results/_site/index.html
934
353
  ----
935
354
 
936
- XML streaming/SAX parsing:
937
355
 
938
- [source]
939
- ----
940
- $ serialbench benchmark --formats xml --streaming-only
941
- ----
942
-
943
- ===== JSON benchmarks
944
-
945
- Run all JSON library benchmarks:
946
-
947
- [source]
948
- ----
949
- $ serialbench benchmark --formats json
950
- ----
951
356
 
952
- Test specific JSON libraries:
953
357
 
954
- [source]
955
- ----
956
- $ serialbench benchmark --formats json --parsers oj,json
957
- $ serialbench benchmark --formats json --parsers yajl,oj
958
- ----
358
+ == Configuration Files
959
359
 
960
- ===== TOML benchmarks
360
+ === Environment configuration
961
361
 
962
- Run all TOML library benchmarks:
362
+ Environment configuration files define how benchmarks are executed in different runtime environments.
963
363
 
964
- [source]
364
+ .Environment configuration for Docker (`config/environments/docker-ruby-3.4.yml`)
365
+ [source,yaml]
965
366
  ----
966
- $ serialbench benchmark --formats toml
367
+ ---
368
+ name: docker-ruby-3.4
369
+ kind: docker
370
+ created_at: '2025-06-13T15:18:43+08:00'
371
+ ruby_build_tag: "3.4.1"
372
+ description: Docker environment for Ruby 3.4 benchmarks
373
+ docker:
374
+ image: 'ruby:3.4-slim'
375
+ dockerfile: '../../docker/Dockerfile.ubuntu'
967
376
  ----
968
377
 
969
- Test specific TOML libraries:
970
-
971
- [source]
378
+ .Environment configuration for ASDF (`config/environments/asdf-ruby-3.3.yml`)
379
+ [source,yaml]
972
380
  ----
973
- $ serialbench benchmark --formats toml --parsers tomlib,toml-rb
381
+ ---
382
+ name: ruby-332-asdf
383
+ kind: asdf
384
+ created_at: '2025-06-12T22:53:24+08:00'
385
+ ruby_build_tag: 3.3.2
386
+ description: ASDF environment
387
+ asdf:
388
+ auto_install: true
974
389
  ----
975
390
 
976
- ==== Cross-format comparisons
391
+ === Benchmark configuration
977
392
 
978
- Compare XML vs JSON performance:
393
+ Benchmark configuration files control what tests to run and how to run them.
979
394
 
980
- [source]
981
- ----
982
- $ serialbench benchmark --formats xml json
983
- ----
984
-
985
- Compare all supported formats:
986
-
987
- [source]
988
- ----
989
- $ serialbench benchmark --formats xml json toml
395
+ .Short configuration (CI-friendly) (`config/benchmarks/short.yml`)
396
+ [source,yaml]
990
397
  ----
398
+ name: short-benchmark
991
399
 
992
- ==== Advanced options
400
+ data_sizes:
401
+ - small
993
402
 
994
- Memory profiling across formats:
403
+ formats:
404
+ - xml
405
+ - json
406
+ - yaml
407
+ - toml
995
408
 
996
- [source]
997
- ----
998
- $ serialbench benchmark --memory-profiling
999
- ----
409
+ iterations:
410
+ small: 5
411
+ medium: 2
412
+ large: 1
1000
413
 
1001
- Generate detailed reports:
414
+ operations:
415
+ - parse
416
+ - generate
417
+ - streaming
1002
418
 
1003
- [source]
1004
- ----
1005
- $ serialbench benchmark --detailed-reports
419
+ warmup: 2
1006
420
  ----
1007
421
 
1008
- Output results in JSON format:
1009
-
1010
- [source]
1011
- ----
1012
- $ serialbench benchmark --output-format json
422
+ .Full configuration (Comprehensive) (`config/benchmarks/full.yml`)
423
+ [source,yaml]
1013
424
  ----
425
+ name: full-benchmark
1014
426
 
1015
- Custom data sizes and iterations:
427
+ data_sizes:
428
+ - small
429
+ - medium
430
+ - large
1016
431
 
1017
- [source]
1018
- ----
1019
- $ serialbench benchmark --data-sizes small,medium --iterations 100
1020
- ----
432
+ formats:
433
+ - xml
434
+ - json
435
+ - yaml
436
+ - toml
1021
437
 
1022
- === Multi-Ruby version comparison
438
+ iterations:
439
+ small: 20
440
+ medium: 5
441
+ large: 2
1023
442
 
1024
- Merge benchmark results from multiple Ruby versions:
443
+ operations:
444
+ - parse
445
+ - generate
446
+ - streaming
447
+ - memory
1025
448
 
1026
- [source]
1027
- ----
1028
- $ serialbench merge_results ruby-3.0/results ruby-3.1/results ruby-3.2/results merged_output/
449
+ warmup: 3
1029
450
  ----
1030
451
 
1031
- Generate GitHub Pages HTML from multiple benchmark runs:
1032
-
1033
- [source]
1034
- ----
1035
- $ serialbench github_pages ruby-3.0/results ruby-3.1/results ruby-3.2/results docs/
1036
- ----
1037
-
1038
- This creates an interactive HTML report with:
1039
-
1040
- * **Multi-version charts**: Compare performance across Ruby versions
1041
- * **Interactive navigation**: Switch between parsing, generation, streaming, and memory usage
1042
- * **Environment details**: Ruby versions, platforms, and serializer versions
1043
- * **GitHub Pages ready**: Deploy directly to GitHub Pages for public sharing
1044
-
1045
- === Cross-platform performance analysis
1046
-
1047
- Analyze performance data from multiple benchmark runs across different platforms and Ruby versions:
1048
-
1049
- [source]
1050
- ----
1051
- $ serialbench analyze_performance artifacts/benchmark-results-*/ performance_analysis.json
1052
- ----
452
+ == Results structure
1053
453
 
1054
- This command:
454
+ === Individual run results
1055
455
 
1056
- * **Processes multiple result directories** from different platforms and Ruby versions
1057
- * **Extracts platform and Ruby version** information from directory names
1058
- * **Generates comprehensive JSON** with detailed performance metrics
1059
- * **Handles both parsing and generation** benchmark results
1060
- * **Provides summary statistics** about processed data
456
+ Results are stored in a structured directory format, with each run containing
457
+ raw benchmark data and execution logs.
1061
458
 
1062
- Generate platform comparison reports:
459
+ The directory is located at `results/runs/{name}/`, where `{name}` is the name
460
+ of the environment used for the benchmark.
1063
461
 
1064
462
  [source]
1065
463
  ----
1066
- $ serialbench platform_comparison performance_analysis.json platform_comparison.json
464
+ results/runs/docker-ruby-33-results/
465
+ ├── results.yaml # Raw benchmark data
466
+ └── benchmark.log # Execution log
1067
467
  ----
1068
468
 
1069
- This creates a JSON report with:
469
+ === ResultSet structure
1070
470
 
1071
- * **Cross-platform statistics**: Average, min, max performance by platform
1072
- * **Format-specific analysis**: Performance breakdown by serialization format
1073
- * **Operation comparison**: Separate analysis for parsing vs generation
1074
- * **Sample counts**: Number of data points for statistical confidence
1075
- * **Standard deviation**: Statistical variance for performance consistency
1076
-
1077
- ==== Example workflow for cross-platform analysis
471
+ ResultSets aggregate multiple benchmark runs for comparison. They are stored in
472
+ a structured directory format at `results/sets/{name}/`, where `{name}` is the
473
+ name of the result set.
1078
474
 
1079
475
  [source]
1080
476
  ----
1081
- # 1. Run benchmarks on different platforms (or use CI artifacts)
1082
- $ serialbench benchmark --formats xml json yaml toml
1083
-
1084
- # 2. Collect results from multiple platforms/Ruby versions
1085
- $ mkdir analysis
1086
- $ cp -r platform1-ruby3.2/results analysis/benchmark-results-ubuntu-ruby-3.2
1087
- $ cp -r platform2-ruby3.3/results analysis/benchmark-results-macos-ruby-3.3
1088
- $ cp -r platform3-ruby3.4/results analysis/benchmark-results-windows-ruby-3.4
1089
-
1090
- # 3. Generate performance analysis
1091
- $ serialbench analyze_performance analysis/benchmark-results-*/ performance_analysis.json
1092
-
1093
- # 4. Create platform comparison report
1094
- $ serialbench platform_comparison performance_analysis.json platform_comparison.json
1095
-
1096
- # 5. View results
1097
- $ cat performance_analysis.json | jq '.summary'
1098
- $ cat performance_analysis.json | jq '.platforms'
1099
- $ cat platform_comparison.json | jq '.platforms'
1100
- ----
1101
-
1102
- The analysis commands are particularly useful for:
1103
-
1104
- * **CI/CD integration**: Automated cross-platform performance tracking
1105
- * **Performance regression detection**: Compare results across builds
1106
- * **Platform optimization**: Identify platform-specific performance characteristics
1107
- * **Ruby version migration**: Analyze performance impact of Ruby upgrades
1108
-
1109
- === Programmatic usage
1110
-
1111
- ==== Basic benchmark execution
1112
-
1113
- [source,ruby]
1114
- ----
1115
- require 'serialbench'
1116
-
1117
- # Run all benchmarks for all formats
1118
- results = Serialbench.run_benchmarks
1119
-
1120
- # Run benchmarks for specific formats
1121
- results = Serialbench.run_benchmarks(formats: [:xml, :json])
1122
-
1123
- # Generate comprehensive reports
1124
- report_files = Serialbench.generate_reports(results)
1125
-
1126
- puts "HTML report: #{report_files[:html]}"
1127
- puts "Charts generated: #{report_files[:charts].length}"
1128
- ----
1129
-
1130
- ==== Custom benchmark configuration
1131
-
1132
- [source,ruby]
1133
- ----
1134
- require 'serialbench'
1135
-
1136
- # Create a custom benchmark runner
1137
- runner = Serialbench::BenchmarkRunner.new(formats: [:json, :xml])
1138
-
1139
- # Run specific benchmark categories
1140
- parsing_results = runner.run_parsing_benchmarks
1141
- generation_results = runner.run_generation_benchmarks
1142
- memory_results = runner.run_memory_benchmarks
1143
-
1144
- # Format and display results
1145
- formatter = Serialbench::ResultFormatter.new(runner.results)
1146
- puts formatter.summary
1147
- ----
1148
-
1149
- ==== Individual serializer testing
1150
-
1151
- [source,ruby]
1152
- ----
1153
- require 'serialbench'
1154
-
1155
- # Test a specific JSON serializer
1156
- oj_serializer = Serialbench::Serializers::Json::OjSerializer.new
1157
-
1158
- if oj_serializer.available?
1159
- json_content = '{"users": [{"name": "Alice", "age": 30}]}'
1160
-
1161
- # Parse JSON
1162
- data = oj_serializer.parse(json_content)
1163
-
1164
- # Generate JSON
1165
- json_output = oj_serializer.generate(data, pretty: true)
1166
-
1167
- # Stream parsing (if supported)
1168
- if oj_serializer.supports_streaming?
1169
- oj_serializer.stream_parse(json_content) do |event, data|
1170
- puts "Event: #{event}, Data: #{data}"
1171
- end
1172
- end
1173
-
1174
- puts "Serializer: #{oj_serializer.name}"
1175
- puts "Version: #{oj_serializer.version}"
1176
- puts "Format: #{oj_serializer.format}"
1177
- puts "Features: #{oj_serializer.features}"
1178
- end
1179
- ----
1180
-
1181
- ==== Check available serializers
1182
-
1183
- [source,ruby]
1184
- ----
1185
- require 'serialbench'
1186
-
1187
- # List all available serializers
1188
- Serialbench.available_serializers.each do |serializer_class|
1189
- serializer = serializer_class.new
1190
- puts "#{serializer.format}: #{serializer.name} v#{serializer.version}"
1191
- end
1192
-
1193
- # List serializers for specific format
1194
- Serialbench.available_serializers(:json).each do |serializer_class|
1195
- serializer = serializer_class.new
1196
- puts "JSON: #{serializer.name} v#{serializer.version}"
1197
- end
477
+ results/sets/ruby-version-comparison/
478
+ └── resultset.yml # Result set configuration
1198
479
  ----
1199
480
 
1200
481
  == Benchmark categories
@@ -1221,105 +502,32 @@ it, which processes data sequentially and is memory-efficient for large files.
1221
502
  Profiles memory allocation and retention during serialization operations using
1222
503
  the `memory_profiler` gem.
1223
504
 
505
+ == Interactive Dashboard Features
1224
506
 
1225
- == Output and reports
1226
-
1227
- === Generated files
1228
-
1229
- Running benchmarks creates the following output structure:
507
+ The generated HTML sites provide comprehensive interactive dashboards with:
1230
508
 
1231
- [source]
1232
- ----
1233
- results/
1234
- ├── reports/
1235
- │ ├── benchmark_report.html # Main HTML report
1236
- │ └── benchmark_report.adoc # AsciiDoc source
1237
- ├── charts/
1238
- │ ├── parsing_performance.svg
1239
- │ ├── generation_performance.svg
1240
- │ ├── streaming_performance.svg
1241
- │ ├── memory_usage_comparison.svg
1242
- │ └── format_comparison.svg
1243
- ├── data/
1244
- │ ├── results.json # Raw benchmark data
1245
- │ └── results.csv # CSV export
1246
- └── assets/
1247
- └── css/
1248
- └── benchmark_report.css # Report styling
1249
- ----
1250
-
1251
- === Report features
1252
-
1253
- * **Multi-format comparison**: Compare XML, JSON, and TOML performance
1254
- * **Interactive charts**: SVG-based performance visualizations
1255
- * **Comparative analysis**: Side-by-side library comparisons
1256
- * **Performance rankings**: Fastest to slowest for each category
1257
- * **Memory profiling**: Detailed memory allocation analysis
1258
- * **Feature matrix**: Capability comparison across libraries
1259
- * **Environment details**: Ruby version, platform, and library versions
1260
-
1261
- === Sample output
1262
-
1263
- [example]
1264
- ====
1265
- Serialbench - Comprehensive Serialization Performance Tests
1266
- ===========================================================
1267
- Environment: Ruby 3.3.2 on arm64-darwin23
1268
- Timestamp: 2025-06-07T10:30:00Z
1269
-
1270
- Available serializers: rexml, json, oj, toml-rb
1271
- Test formats: xml, json, toml
1272
- Test data sizes: small, medium, large
1273
-
1274
- Parsing Performance:
1275
- Small files:
1276
- JSON/oj: 0.08ms
1277
- JSON/json: 0.12ms
1278
- XML/rexml: 0.45ms
1279
- TOML/toml-rb: 0.52ms
1280
-
1281
- Medium files:
1282
- JSON/oj: 8.23ms
1283
- JSON/json: 12.67ms
1284
- XML/rexml: 28.45ms
1285
- TOML/toml-rb: 35.21ms
1286
- ====
1287
-
1288
- == Methodology
509
+ === Navigation and Filtering
510
+ * **Format tabs**: Dedicated views for XML, JSON, YAML, and TOML
511
+ * **Operation sections**: Parsing, generation, streaming, and memory usage
512
+ * **Dynamic filtering**: Platform, Ruby version, and environment selection
513
+ * **Real-time updates**: Charts update instantly based on filter selections
1289
514
 
1290
- === Performance measurement
515
+ === Visualization Capabilities
516
+ * **Chart.js integration**: Interactive performance charts with hover details
517
+ * **Multi-scale handling**: Automatic Y-axis scaling for different performance ranges
518
+ * **Color-coded data**: Consistent color schemes across serializers and environments
519
+ * **Responsive design**: Optimized for desktop and mobile viewing
1291
520
 
1292
- * Each test runs multiple iterations with warmup iterations
1293
- * Memory profiling uses 10 iterations to reduce noise
1294
- * Results show average performance across all iterations
1295
- * Benchmarks use Ruby's `Benchmark.realtime` for precise timing
521
+ === User Experience
522
+ * **Theme toggle**: Light and dark mode with persistent preferences
523
+ * **Keyboard navigation**: Full accessibility support
524
+ * **Fast loading**: Optimized JavaScript for quick dashboard initialization
525
+ * **Export capabilities**: JSON data export for further analysis
1296
526
 
1297
- === Test data
1298
-
1299
- ==== Synthetic datasets
1300
-
1301
- The benchmark suite uses carefully crafted synthetic data that represents common real-world scenarios:
1302
-
1303
- * **Configuration files**: Small, nested structures typical of application settings
1304
- * **API responses**: Medium-sized documents with repeated record structures
1305
- * **Data exports**: Large documents with extensive hierarchical data
1306
-
1307
- ==== Multi-format consistency
1308
-
1309
- * Equivalent data structures across XML, JSON, and TOML formats
1310
- * Consistent complexity and nesting levels
1311
- * Representative of real-world usage patterns
1312
-
1313
- === Statistical considerations
1314
-
1315
- * Multiple iterations reduce timing variance
1316
- * Warmup iterations eliminate JIT compilation effects
1317
- * Memory measurements account for garbage collection
1318
- * Results include both absolute and relative performance metrics
1319
527
 
1320
528
  == Development
1321
529
 
1322
- === Running tests
530
+ === Running Tests
1323
531
 
1324
532
  [source]
1325
533
  ----
@@ -1327,15 +535,7 @@ $ bundle exec rake
1327
535
  $ bundle exec rspec
1328
536
  ----
1329
537
 
1330
- === Contributing
1331
-
1332
- . Fork the repository
1333
- . Create your feature branch (`git checkout -b feature/my-new-feature`)
1334
- . Commit your changes (`git commit -am 'Add some feature'`)
1335
- . Push to the branch (`git push origin feature/my-new-feature`)
1336
- . Create a new Pull Request
1337
-
1338
- === Adding new serializers
538
+ === Adding a new serializers
1339
539
 
1340
540
  To add support for additional serialization libraries:
1341
541
 
@@ -1345,76 +545,50 @@ To add support for additional serialization libraries:
1345
545
  . Add the serializer to the registry in `lib/serialbench/serializers.rb`
1346
546
  . Update documentation and tests
1347
547
 
1348
- ==== Example: Adding a new JSON serializer
548
+ === Contributing
1349
549
 
1350
- [source,ruby]
1351
- ----
1352
- # lib/serialbench/serializers/json/yajl_serializer.rb
1353
- class YajlSerializer < BaseJsonSerializer
1354
- def available?
1355
- require_library('yajl')
1356
- end
1357
-
1358
- def name
1359
- 'yajl'
1360
- end
1361
-
1362
- def version
1363
- require 'yajl'
1364
- Yajl::VERSION
1365
- end
1366
-
1367
- def parse(json_string)
1368
- require 'yajl'
1369
- Yajl::Parser.parse(json_string)
1370
- end
1371
-
1372
- def generate(object, options = {})
1373
- require 'yajl'
1374
- Yajl::Encoder.encode(object)
1375
- end
1376
- end
1377
- ----
550
+ . Fork the repository
551
+ . Create your feature branch (`git checkout -b feature/my-new-feature`)
552
+ . Commit your changes (`git commit -am 'Add some feature'`)
553
+ . Push to the branch (`git push origin feature/my-new-feature`)
554
+ . Create a new Pull Request
1378
555
 
1379
- == Architecture
1380
556
 
1381
- === Serializer hierarchy
557
+ == Known issues
1382
558
 
1383
- [source]
1384
- ----
1385
- BaseSerializer
1386
- ├── BaseXmlSerializer
1387
- │ └── RexmlSerializer
1388
- ├── BaseJsonSerializer
1389
- │ ├── JsonSerializer
1390
- │ └── OjSerializer
1391
- └── BaseTomlSerializer
1392
- └── TomlRbSerializer
1393
- ----
559
+ === Syck YAML serializer segmentation faults
1394
560
 
1395
- === Key components
561
+ The Syck YAML serializer at version 1.5+ is known to cause segmentation faults
562
+ on Ruby 3.1 and later versions. Serialbench automatically detects this
563
+ problematic configuration and:
1396
564
 
1397
- * **Serializers**: Individual library implementations
1398
- * **BenchmarkRunner**: Orchestrates benchmark execution
1399
- * **ResultFormatter**: Formats and displays results
1400
- * **ReportGenerator**: Creates HTML/AsciiDoc reports
1401
- * **ChartGenerator**: Creates performance visualizations
1402
- * **MemoryProfiler**: Analyzes memory usage patterns
565
+ * Displays a warning message when Syck is detected on Ruby 3.1+
566
+ * Skips Syck benchmarks to prevent crashes
567
+ * Continues with other YAML serializers (Psych)
1403
568
 
1404
- == Research and references
569
+ === Syck overrides YAML constant
1405
570
 
1406
- This benchmarking suite was developed based on research from:
571
+ On occasion after Syck is loaded, the constant `YAML` may be redefined to
572
+ `Syck`, which can cause issues in other parts of the codebase. This can cause
573
+ YAML output to fail when using libraries that expect `YAML` to have the
574
+ `Psych` API.
575
+
576
+ In `benchmark_cli.rb` there is therefore such code to ensure that
577
+ `YAML` is defined as `Psych` when writing to file is needed:
578
+
579
+ [source,ruby]
580
+ ----
581
+ # Restore YAML to use Psych for output, otherwise lutaml-model's to_yaml
582
+ # will have no output
583
+ Object.const_set(:YAML, Psych)
584
+ ----
1407
585
 
1408
- * https://www.ohler.com/dev/xml_with_ruby/xml_with_ruby.html[XML with Ruby performance analysis]
1409
- * https://gist.github.com/danneu/3977120[Ruby XML parser comparison]
1410
- * https://gist.github.com/adilosa/d4277dc1c683da91990515352ffe5420[XML parsing benchmarks]
1411
586
 
1412
- == Copyright
587
+ == License and copyright
1413
588
 
1414
- This gem is developed, maintained and funded by
1415
- https://www.ribose.com[Ribose Inc.]
589
+ Copyright Ribose.
1416
590
 
1417
- == License
591
+ This gem is developed, maintained and funded by https://www.ribose.com[Ribose]
1418
592
 
1419
593
  The gem is available as open source under the terms of the
1420
594
  https://opensource.org/licenses/BSD-2-Clause[2-Clause BSD License].