serialbench 0.1.0 → 0.1.2

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 (85) hide show
  1. checksums.yaml +4 -4
  2. data/.github/workflows/benchmark.yml +181 -30
  3. data/.github/workflows/ci.yml +3 -3
  4. data/.github/workflows/docker.yml +272 -0
  5. data/.github/workflows/rake.yml +15 -0
  6. data/.github/workflows/release.yml +25 -0
  7. data/Gemfile +6 -30
  8. data/README.adoc +381 -415
  9. data/Rakefile +0 -55
  10. data/config/benchmarks/full.yml +29 -0
  11. data/config/benchmarks/short.yml +26 -0
  12. data/config/environments/asdf-ruby-3.2.yml +8 -0
  13. data/config/environments/asdf-ruby-3.3.yml +8 -0
  14. data/config/environments/docker-ruby-3.0.yml +9 -0
  15. data/config/environments/docker-ruby-3.1.yml +9 -0
  16. data/config/environments/docker-ruby-3.2.yml +9 -0
  17. data/config/environments/docker-ruby-3.3.yml +9 -0
  18. data/config/environments/docker-ruby-3.4.yml +9 -0
  19. data/docker/Dockerfile.alpine +33 -0
  20. data/docker/Dockerfile.ubuntu +32 -0
  21. data/docker/README.md +214 -0
  22. data/exe/serialbench +1 -1
  23. data/lib/serialbench/benchmark_runner.rb +270 -350
  24. data/lib/serialbench/cli/base_cli.rb +51 -0
  25. data/lib/serialbench/cli/benchmark_cli.rb +380 -0
  26. data/lib/serialbench/cli/environment_cli.rb +181 -0
  27. data/lib/serialbench/cli/resultset_cli.rb +215 -0
  28. data/lib/serialbench/cli/ruby_build_cli.rb +238 -0
  29. data/lib/serialbench/cli.rb +59 -410
  30. data/lib/serialbench/config_manager.rb +140 -0
  31. data/lib/serialbench/models/benchmark_config.rb +63 -0
  32. data/lib/serialbench/models/benchmark_result.rb +45 -0
  33. data/lib/serialbench/models/environment_config.rb +71 -0
  34. data/lib/serialbench/models/platform.rb +59 -0
  35. data/lib/serialbench/models/result.rb +53 -0
  36. data/lib/serialbench/models/result_set.rb +71 -0
  37. data/lib/serialbench/models/result_store.rb +108 -0
  38. data/lib/serialbench/models.rb +54 -0
  39. data/lib/serialbench/ruby_build_manager.rb +153 -0
  40. data/lib/serialbench/runners/asdf_runner.rb +296 -0
  41. data/lib/serialbench/runners/base.rb +32 -0
  42. data/lib/serialbench/runners/docker_runner.rb +142 -0
  43. data/lib/serialbench/serializers/base_serializer.rb +8 -16
  44. data/lib/serialbench/serializers/json/base_json_serializer.rb +4 -4
  45. data/lib/serialbench/serializers/json/json_serializer.rb +0 -2
  46. data/lib/serialbench/serializers/json/oj_serializer.rb +0 -2
  47. data/lib/serialbench/serializers/json/rapidjson_serializer.rb +50 -0
  48. data/lib/serialbench/serializers/json/yajl_serializer.rb +6 -4
  49. data/lib/serialbench/serializers/toml/base_toml_serializer.rb +5 -3
  50. data/lib/serialbench/serializers/toml/toml_rb_serializer.rb +0 -2
  51. data/lib/serialbench/serializers/toml/tomlib_serializer.rb +0 -2
  52. data/lib/serialbench/serializers/toml/tomlrb_serializer.rb +56 -0
  53. data/lib/serialbench/serializers/xml/base_xml_serializer.rb +4 -9
  54. data/lib/serialbench/serializers/xml/libxml_serializer.rb +0 -2
  55. data/lib/serialbench/serializers/xml/nokogiri_serializer.rb +21 -5
  56. data/lib/serialbench/serializers/xml/oga_serializer.rb +0 -2
  57. data/lib/serialbench/serializers/xml/ox_serializer.rb +0 -2
  58. data/lib/serialbench/serializers/xml/rexml_serializer.rb +32 -4
  59. data/lib/serialbench/serializers/yaml/base_yaml_serializer.rb +59 -0
  60. data/lib/serialbench/serializers/yaml/psych_serializer.rb +54 -0
  61. data/lib/serialbench/serializers/yaml/syck_serializer.rb +102 -0
  62. data/lib/serialbench/serializers.rb +34 -6
  63. data/lib/serialbench/site_generator.rb +105 -0
  64. data/lib/serialbench/templates/assets/css/benchmark_report.css +535 -0
  65. data/lib/serialbench/templates/assets/css/format_based.css +526 -0
  66. data/lib/serialbench/templates/assets/css/themes.css +588 -0
  67. data/lib/serialbench/templates/assets/js/chart_helpers.js +381 -0
  68. data/lib/serialbench/templates/assets/js/dashboard.js +796 -0
  69. data/lib/serialbench/templates/assets/js/navigation.js +142 -0
  70. data/lib/serialbench/templates/base.liquid +49 -0
  71. data/lib/serialbench/templates/format_based.liquid +279 -0
  72. data/lib/serialbench/templates/partials/chart_section.liquid +4 -0
  73. data/lib/serialbench/version.rb +1 -1
  74. data/lib/serialbench.rb +2 -31
  75. data/serialbench.gemspec +28 -17
  76. metadata +192 -55
  77. data/lib/serialbench/chart_generator.rb +0 -821
  78. data/lib/serialbench/result_formatter.rb +0 -182
  79. data/lib/serialbench/result_merger.rb +0 -1201
  80. data/lib/serialbench/serializers/xml/base_parser.rb +0 -69
  81. data/lib/serialbench/serializers/xml/libxml_parser.rb +0 -98
  82. data/lib/serialbench/serializers/xml/nokogiri_parser.rb +0 -111
  83. data/lib/serialbench/serializers/xml/oga_parser.rb +0 -85
  84. data/lib/serialbench/serializers/xml/ox_parser.rb +0 -64
  85. data/lib/serialbench/serializers/xml/rexml_parser.rb +0 -129
data/README.adoc CHANGED
@@ -1,592 +1,558 @@
1
- = Serialbench: Comprehensive serialization benchmarking suite for Ruby
1
+ = Serialbench: Ruby serialization library performance benchmarker
2
2
 
3
3
  image:https://img.shields.io/gem/v/serialbench.svg["Gem Version", link="https://rubygems.org/gems/serialbench"]
4
- image:https://github.com/example/serialbench/actions/workflows/rake.yml/badge.svg["Build Status", link="https://github.com/example/serialbench/actions/workflows/rake.yml"]
5
- image:https://img.shields.io/github/issues-pr-raw/example/serialbench.svg["Pull Requests", link="https://github.com/example/serialbench/pulls"]
6
- image:https://img.shields.io/github/commits-since/example/serialbench/latest.svg["Commits since latest",link="https://github.com/example/serialbench/releases"]
4
+ image:https://github.com/metanorma/serialbench/actions/workflows/ci.yml/badge.svg["Build Status", link="https://github.com/metanorma/serialbench/actions/workflows/ci.yml"]
5
+ image:https://github.com/metanorma/serialbench/actions/workflows/benchmark.yml/badge.svg["Benchmark Status", link="https://github.com/metanorma/serialbench/actions/workflows/benchmark.yml"]
6
+ image:https://img.shields.io/github/issues-pr-raw/metanorma/serialbench.svg["Pull Requests", link="https://github.com/metanorma/serialbench/pulls"]
7
7
 
8
- == Purpose
8
+ == Overview
9
9
 
10
- Serialbench is a comprehensive benchmarking suite that evaluates the performance of popular Ruby serialization libraries across multiple formats and dimensions including parsing speed, generation speed, memory usage, and feature completeness.
10
+ Serialbench is a comprehensive benchmarking suite that evaluates the performance of popular Ruby serialization libraries across multiple formats. It provides detailed performance comparisons and analysis to help developers make informed decisions when choosing serialization libraries for their Ruby applications.
11
11
 
12
- This tool helps developers make informed decisions when choosing serialization libraries for their Ruby applications by providing detailed performance comparisons and analysis across XML, JSON, and TOML formats.
12
+ **Supported Formats**: XML, JSON, YAML, TOML, and more
13
13
 
14
- === Tested XML libraries
14
+ **Key Metrics**: Parsing speed, generation speed, memory usage, streaming capabilities, and feature completeness
15
15
 
16
- ==== Core XML Libraries
17
- * **Ox** - High-performance XML parser optimized for speed and low memory usage
18
- * **Nokogiri** - Feature-rich XML/HTML parser with XPath support and comprehensive DOM manipulation
19
- * **LibXML** - Ruby bindings for the libxml2 C library with excellent performance characteristics
20
- * **Oga** - Pure Ruby XML parser with XPath support and streaming capabilities
21
- * **REXML** - Ruby's built-in XML parser with streaming support (reference implementation)
16
+ **Multi-Environment Support**: Docker and ASDF-based multi-Ruby version benchmarking with automated result aggregation and HTML site generation
22
17
 
23
- ==== Additional Format Support
24
- * **JSON** - Ruby's built-in JSON parser (for comparison baseline)
25
- * **Oj** - High-performance JSON parser with streaming support (for comparison baseline)
26
- * **YAJL** - Yet Another JSON Library with streaming support (for comparison baseline)
27
- * **TOML-RB** - Ruby TOML parser (for comparison baseline)
28
- * **Tomlib** - Fast TOML parser (for comparison baseline)
18
+ == Supported serialization libraries
29
19
 
30
- == Installation
20
+ [cols="1,3,1,4", options="header"]
21
+ |===
22
+ | Format | Name | Version | Description
23
+
24
+ | XML
25
+ | https://github.com/ohler55/ox[Ox]
26
+ | v2.14.23
27
+ | C extension XML parser
28
+
29
+ | XML
30
+ | https://github.com/xml4r/libxml-ruby[LibXML]
31
+ | v4.1.2
32
+ | Ruby bindings for libxml2
33
+
34
+ | XML
35
+ | https://github.com/sparklemotion/nokogiri[Nokogiri]
36
+ | v1.18.8
37
+ | XML/HTML parser with XPath and CSS selectors
38
+
39
+ | XML
40
+ | https://github.com/YorickPeterse/oga[Oga]
41
+ | v3.4
42
+ | Pure Ruby XML parser with XPath support
43
+
44
+ | XML
45
+ | https://github.com/ruby/rexml[REXML]
46
+ | v3.4.1
47
+ | Ruby's standard library XML parser
48
+
49
+ | JSON
50
+ | https://github.com/ohler55/oj[Oj]
51
+ | v3.16.11
52
+ | JSON parser with multiple parsing modes
53
+
54
+ | JSON
55
+ | https://github.com/brianmario/yajl-ruby[YAJL]
56
+ | v1.4.3
57
+ | JSON library with streaming capabilities
58
+
59
+ | JSON
60
+ | https://github.com/flori/json[JSON]
61
+ | v2.12.2
62
+ | Ruby's standard library JSON parser
63
+
64
+ | YAML
65
+ | https://github.com/ruby/psych[Psych]
66
+ | v5.1.2
67
+ | Ruby's standard library YAML parser
68
+
69
+ | YAML
70
+ | https://github.com/ruby/syck[Syck]
71
+ | v1.5.1.1
72
+ | Legacy YAML parser
73
+
74
+ | TOML
75
+ | https://github.com/fbernier/tomlib[Tomlib]
76
+ | v0.7.3
77
+ | TOML parser implemented in C
78
+
79
+ | TOML
80
+ | https://github.com/emancu/toml-rb[TOML-RB]
81
+ | v2.2.0
82
+ | Pure Ruby TOML parser
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.)
31
88
 
32
- Add this line to your application's Gemfile:
89
+ |===
33
90
 
34
- [source,ruby]
35
- ----
36
- gem 'serialbench'
37
- ----
38
91
 
39
- And then execute:
92
+ == Data formats and schema
40
93
 
41
- [source,shell]
42
- ----
43
- $ bundle install
44
- ----
94
+ Serialbench generates structured YAML output for benchmark results, with
95
+ different formats for single-environment and multi-environment runs.
45
96
 
46
- Or install it yourself as:
97
+ The data formats include:
47
98
 
48
- [source,shell]
49
- ----
50
- $ gem install serialbench
51
- ----
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
52
103
 
53
- === XML library dependencies
104
+ == Prerequisites
54
105
 
55
- To run benchmarks for all supported XML libraries, install the following gems:
106
+ === System requirements
56
107
 
57
- [source,shell]
58
- ----
59
- # Core XML libraries
60
- $ gem install ox nokogiri libxml-ruby oga
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
61
111
 
62
- # Additional format libraries (for comparison)
63
- $ gem install oj toml-rb
112
+ === Library dependencies
64
113
 
65
- # Memory profiling support
66
- $ gem install memory_profiler
67
- ----
68
-
69
- NOTE: REXML and JSON are included with Ruby and require no additional installation.
70
-
71
- === Library-specific installation notes
72
-
73
- ==== Ox
74
- High-performance C extension requiring compilation:
75
- [source,shell]
76
- ----
77
- $ gem install ox
78
- ----
114
+ **System dependencies** (required for some native extensions):
79
115
 
80
- ==== Nokogiri
81
- May require system dependencies on some platforms:
82
- [source,shell]
116
+ [source,bash]
83
117
  ----
84
118
  # macOS with Homebrew
85
119
  $ brew install libxml2 libxslt
86
- $ gem install nokogiri
87
-
88
- # Ubuntu/Debian
89
- $ sudo apt-get install libxml2-dev libxslt1-dev
90
- $ gem install nokogiri
91
- ----
92
-
93
- ==== LibXML
94
- Ruby bindings for libxml2:
95
- [source,shell]
96
- ----
97
- # macOS with Homebrew
98
- $ brew install libxml2
99
- $ gem install libxml-ruby
100
120
 
101
121
  # Ubuntu/Debian
102
- $ sudo apt-get install libxml2-dev
103
- $ gem install libxml-ruby
104
- ----
122
+ $ sudo apt-get install libxml2-dev libxslt1-dev build-essential
105
123
 
106
- ==== Oga
107
- Pure Ruby implementation with no system dependencies:
108
- [source,shell]
109
- ----
110
- $ gem install oga
124
+ # CentOS/RHEL/Fedora
125
+ $ sudo yum install libxml2-devel libxslt-devel gcc gcc-c++
111
126
  ----
112
127
 
113
- == Usage
114
-
115
- === Command line interface
128
+ == Installation
116
129
 
117
- Run the complete XML benchmark suite:
130
+ Add this line to your application's Gemfile:
118
131
 
119
- [source,shell]
132
+ [source,ruby]
120
133
  ----
121
- $ serialbench benchmark
134
+ gem 'serialbench'
122
135
  ----
123
136
 
124
- Run XML-only benchmarks:
137
+ And then execute:
125
138
 
126
- [source,shell]
139
+ [source]
127
140
  ----
128
- $ serialbench benchmark --formats xml
141
+ $ bundle install
129
142
  ----
130
143
 
131
- Run benchmarks with comparison formats:
144
+ Or install it yourself as:
132
145
 
133
- [source,shell]
146
+ [source]
134
147
  ----
135
- $ serialbench benchmark --formats xml json
136
- $ serialbench benchmark --formats xml json toml
148
+ $ gem install serialbench
137
149
  ----
138
150
 
139
- Run only DOM parsing benchmarks:
140
-
141
- [source,shell]
142
- ----
143
- $ serialbench benchmark --parsing-only
144
- ----
145
151
 
146
- Run only XML generation benchmarks:
152
+ == Command line interface
147
153
 
148
- [source,shell]
149
- ----
150
- $ serialbench benchmark --generation-only
151
- ----
154
+ Serialbench provides a comprehensive Thor-based CLI with four main subcommands
155
+ for managing environments, benchmarks, result sets, and Ruby builds.
152
156
 
153
- Run only streaming/SAX parsing benchmarks:
157
+ === Main Commands Overview
154
158
 
155
- [source,shell]
159
+ [source,sh]
156
160
  ----
157
- $ serialbench benchmark --streaming-only
158
- ----
159
-
160
- Output results in JSON format only:
161
+ $ serialbench
162
+ Serialbench - Benchmarking Framework for Ruby Serialization Libraries
161
163
 
162
- [source,shell]
163
- ----
164
- $ serialbench benchmark --output-format json
165
- ----
164
+ USAGE:
165
+ serialbench COMMAND [SUBCOMMAND] [OPTIONS]
166
166
 
167
- List available XML parsers:
167
+ COMMANDS:
168
+ environment Manage benchmark environments (Docker, ASDF, Local)
169
+ benchmark Manage individual benchmark runs
170
+ resultset Manage benchmark resultsets (collections of runs)
171
+ ruby-build Manage Ruby-Build definitions for validation
172
+ version Show version information
173
+ help Show this help message
168
174
 
169
- [source,shell]
170
- ----
171
- $ serialbench list
172
- $ serialbench list --format xml
173
- ----
175
+ EXAMPLES:
176
+ # Create a Docker environment
177
+ serialbench environment new docker-test docker
174
178
 
175
- Show help information:
179
+ # Run multi-environment benchmarks
180
+ serialbench environment multi-execute asdf --config=serialbench-asdf.yml
181
+ serialbench environment multi-execute docker --config=serialbench-docker.yml
176
182
 
177
- [source,shell]
178
- ----
179
- $ serialbench help
180
- $ serialbench help benchmark
181
- ----
183
+ # Create and execute a benchmark
184
+ serialbench benchmark create my-benchmark
185
+ serialbench benchmark execute my-benchmark.yml
182
186
 
183
- Show version:
187
+ # Create a result set for comparison
188
+ serialbench resultset create comparison-set
189
+ serialbench resultset add-result comparison-set results/my-benchmark
184
190
 
185
- [source,shell]
186
- ----
187
- $ serialbench version
191
+ # Generate static sites
192
+ serialbench benchmark build-site results/my-benchmark
193
+ serialbench resultset build-site resultsets/comparison-set
188
194
  ----
189
195
 
190
- === XML-specific benchmark options
196
+ === Environment management
191
197
 
192
- Run benchmarks for specific XML libraries only:
198
+ The `environment` subcommand manages environment configurations and executes
199
+ benchmarks across different Ruby environments.
193
200
 
194
- [source,shell]
201
+ [source]
195
202
  ----
196
- $ serialbench benchmark --formats xml --parsers ox,nokogiri
197
- $ serialbench benchmark --formats xml --parsers rexml,oga
203
+ $ serialbench environment help
204
+ Commands:
205
+ serialbench environment execute ENVIRONMENT_CONFIG BENCHMARK_CONFIG RESULT_PATH # Execute benchmark in environment
206
+ serialbench environment help [COMMAND] # Describe subcommands or one specific subcommand
207
+ serialbench environment new NAME KIND RUBY_BUILD_TAG # Create a new environment configuration
208
+ serialbench environment prepare ENVIRONMENT_CONFIG # Prepare environment for benchmarking
198
209
  ----
199
210
 
200
- Run memory-intensive benchmarks:
201
211
 
202
- [source,shell]
203
- ----
204
- $ serialbench benchmark --formats xml --memory-profiling
205
- ----
212
+ === Benchmark management
206
213
 
207
- Generate detailed XML processing reports:
214
+ The `benchmark` subcommand handles individual benchmark runs and site generation.
208
215
 
209
- [source,shell]
216
+ [source]
210
217
  ----
211
- $ serialbench benchmark --formats xml --detailed-reports
218
+ $ serialbench benchmark help
219
+ Commands:
220
+ serialbench benchmark _docker_execute ENVIRONMENT_CONFIG_PATH BENCHMARK_CONFIG_PATH # (Private) Execute a benchmark run
221
+ serialbench benchmark build-site RUN_PATH [OUTPUT_DIR] # Generate HTML site for a run
222
+ serialbench benchmark create [NAME] # Generate a run configuration file
223
+ serialbench benchmark execute ENVIRONMENT_CONFIG_PATH BENCHMARK_CONFIG_PATH # Execute a benchmark run
224
+ serialbench benchmark help [COMMAND] # Describe subcommands or one specific subcommand
225
+ serialbench benchmark list # List all available runs
212
226
  ----
213
227
 
214
- === Multi-Ruby Version Comparison
228
+ The `_docker_execute` command is a private command used internally by the
229
+ `execute` command to run benchmarks in Docker environments.
215
230
 
216
- Merge benchmark results from multiple Ruby versions:
217
231
 
218
- [source,shell]
219
- ----
220
- $ serialbench merge_results ruby-3.0/results ruby-3.1/results ruby-3.2/results merged_output/
221
- ----
232
+ === Result set management
222
233
 
223
- Generate GitHub Pages HTML from multiple benchmark runs:
234
+ The `resultset` subcommand manages collections of benchmark runs for comparison analysis.
224
235
 
225
- [source,shell]
236
+ [source]
226
237
  ----
227
- $ serialbench github_pages ruby-3.0/results ruby-3.1/results ruby-3.2/results docs/
238
+ $ serialbench resultset help
239
+ Commands:
240
+ serialbench resultset add-result RESULT_PATH RESULTSET_PATH # Add a run to a resultset
241
+ serialbench resultset build-site RESULTSET_PATH [OUTPUT_DIR] # Generate HTML site for a resultset
242
+ serialbench resultset create NAME PATH # Create a new resultset
243
+ serialbench resultset help [COMMAND] # Describe subcommands or one specific subcommand
244
+ serialbench resultset list # List all available resultsets
245
+ serialbench resultset remove-result RESULTSET_PATH RESULT_PATH # Remove a run from a resultset
228
246
  ----
229
247
 
230
- This creates an interactive HTML report with:
231
248
 
232
- * **Multi-version charts**: Compare performance across Ruby versions
233
- * **Interactive navigation**: Switch between parsing, generation, streaming, and memory usage
234
- * **Environment details**: Ruby versions, platforms, and serializer versions
235
- * **GitHub Pages ready**: Deploy directly to GitHub Pages for public sharing
249
+ === ruby-build management
236
250
 
237
- === Programmatic usage
251
+ The `ruby-build` subcommand manages Ruby build definitions and version information.
238
252
 
239
- ==== Basic benchmark execution
253
+ Serialbench uses ruby-build definitions of Ruby interpreter types and versions
254
+ for identification.
240
255
 
241
- [source,ruby]
256
+ [source]
257
+ ----
258
+ $ serialbench ruby-build help
259
+ Commands:
260
+ serialbench ruby_build cache-info # Show information about the Ruby-Build definitions cache
261
+ serialbench ruby_build help [COMMAND] # Describe subcommands or one specific subcommand
262
+ serialbench ruby_build list [FILTER] # List available Ruby-Build definitions
263
+ serialbench ruby_build show TAG # Show details for a specific Ruby-Build definition
264
+ serialbench ruby_build suggest # Suggest Ruby-Build tag for current Ruby version
265
+ serialbench ruby_build update # Update Ruby-Build definitions from GitHub
266
+ serialbench ruby_build validate TAG # Validate a Ruby-Build tag
242
267
  ----
243
- require 'serialbench'
244
-
245
- # Run all benchmarks for all formats
246
- results = Serialbench.run_benchmarks
247
268
 
248
- # Run benchmarks for specific formats
249
- results = Serialbench.run_benchmarks(formats: [:xml, :json])
250
269
 
251
- # Generate comprehensive reports
252
- report_files = Serialbench.generate_reports(results)
270
+ == Workflow examples
253
271
 
254
- puts "HTML report: #{report_files[:html]}"
255
- puts "Charts generated: #{report_files[:charts].length}"
256
- ----
272
+ === Docker-based testing
257
273
 
258
- ==== Custom benchmark configuration
274
+ NOTE: This works.
259
275
 
260
- [source,ruby]
276
+ [source,bash]
261
277
  ----
262
- require 'serialbench'
278
+ # 1. Prepare Docker environment
279
+ $ bundle exec serialbench environment prepare config/environments/docker-ruby-3.1.yml
263
280
 
264
- # Create a custom benchmark runner
265
- runner = Serialbench::BenchmarkRunner.new(formats: [:json, :xml])
281
+ # 2. Run benchmark
282
+ $ bundle exec serialbench environment execute config/environments/docker-ruby-3.1.yml config/benchmarks/short.yml results/runs/docker-ruby-3.1-results
266
283
 
267
- # Run specific benchmark categories
268
- parsing_results = runner.run_parsing_benchmarks
269
- generation_results = runner.run_generation_benchmarks
270
- memory_results = runner.run_memory_benchmarks
284
+ # 3. Create a resultset
285
+ $ bundle exec serialbench resultset create docker-comparison results/sets/docker-comparison
271
286
 
272
- # Format and display results
273
- formatter = Serialbench::ResultFormatter.new(runner.results)
274
- puts formatter.summary
275
- ----
287
+ # 3a. (Optional) Build the site from the result if you want to visualize results
288
+ $ bundle exec serialbench benchmark build-site results/runs/docker-ruby-3.1-results/ --output_dir=_site_result
276
289
 
277
- ==== Individual serializer testing
290
+ # 4. Add the result to the resultset
291
+ $ bundle exec serialbench resultset add-result results/sets/docker-comparison/ results/runs/docker-ruby-3.1-results/
278
292
 
279
- [source,ruby]
293
+ # 5. Build the site from the resultset
294
+ $ bundle exec serialbench resultset build-site results/sets/docker-comparison/
295
+
296
+ # 6. Open the generated site
297
+ $ open _site/index.html
280
298
  ----
281
- require 'serialbench'
282
299
 
283
- # Test a specific JSON serializer
284
- oj_serializer = Serialbench::Serializers::Json::OjSerializer.new
300
+ === ASDF-based testing
285
301
 
286
- if oj_serializer.available?
287
- json_content = '{"users": [{"name": "Alice", "age": 30}]}'
302
+ WARNING: THIS IS NOT YET WORKING.
288
303
 
289
- # Parse JSON
290
- data = oj_serializer.parse(json_content)
304
+ [source,bash]
305
+ ----
306
+ # 1. Validate configuration
307
+ $ bundle exec serialbench benchmark validate serialbench-asdf.yml
291
308
 
292
- # Generate JSON
293
- json_output = oj_serializer.generate(data, pretty: true)
309
+ # 2. Prepare Ruby environments
310
+ $ bundle exec serialbench benchmark prepare asdf --config=serialbench-asdf.yml
294
311
 
295
- # Stream parsing (if supported)
296
- if oj_serializer.supports_streaming?
297
- oj_serializer.stream_parse(json_content) do |event, data|
298
- puts "Event: #{event}, Data: #{data}"
299
- end
300
- end
312
+ # 3. Run benchmarks across all Ruby versions
313
+ $ bundle exec serialbench benchmark execute asdf --config=serialbench-asdf.yml
301
314
 
302
- puts "Serializer: #{oj_serializer.name}"
303
- puts "Version: #{oj_serializer.version}"
304
- puts "Format: #{oj_serializer.format}"
305
- puts "Features: #{oj_serializer.features}"
306
- end
315
+ # 4. Results are automatically merged and dashboard generated
316
+ $ open asdf-results/_site/index.html
307
317
  ----
308
318
 
309
- ==== Check available serializers
310
319
 
311
- [source,ruby]
312
- ----
313
- require 'serialbench'
314
-
315
- # List all available serializers
316
- Serialbench.available_serializers.each do |serializer_class|
317
- serializer = serializer_class.new
318
- puts "#{serializer.format}: #{serializer.name} v#{serializer.version}"
319
- end
320
320
 
321
- # List serializers for specific format
322
- Serialbench.available_serializers(:json).each do |serializer_class|
323
- serializer = serializer_class.new
324
- puts "JSON: #{serializer.name} v#{serializer.version}"
325
- end
326
- ----
327
321
 
328
- == Benchmark categories
322
+ == Configuration Files
329
323
 
330
- === Parsing performance
324
+ === Environment configuration
331
325
 
332
- Measures the time required to parse serialized data into Ruby objects.
326
+ Environment configuration files define how benchmarks are executed in different runtime environments.
333
327
 
334
- * **Small files**: ~1KB configuration-style documents
335
- * **Medium files**: ~1MB API responses with 1,000 records
336
- * **Large files**: ~10MB data exports with 10,000 records
337
-
338
- === Generation performance
328
+ .Environment configuration for Docker (`config/environments/docker-ruby-3.4.yml`)
329
+ [source,yaml]
330
+ ----
331
+ ---
332
+ name: docker-ruby-3.4
333
+ kind: docker
334
+ created_at: '2025-06-13T15:18:43+08:00'
335
+ ruby_build_tag: "3.4.1"
336
+ description: Docker environment for Ruby 3.4 benchmarks
337
+ docker:
338
+ image: 'ruby:3.4-slim'
339
+ dockerfile: '../../docker/Dockerfile.ubuntu'
340
+ ----
339
341
 
340
- Tests how quickly libraries can convert Ruby objects into serialized strings.
342
+ .Environment configuration for ASDF (`config/environments/asdf-ruby-3.3.yml`)
343
+ [source,yaml]
344
+ ----
345
+ ---
346
+ name: ruby-332-asdf
347
+ kind: asdf
348
+ created_at: '2025-06-12T22:53:24+08:00'
349
+ ruby_build_tag: 3.3.2
350
+ description: ASDF environment
351
+ asdf:
352
+ auto_install: true
353
+ ----
341
354
 
342
- === Streaming performance
355
+ === Benchmark configuration
343
356
 
344
- Evaluates streaming event-based parsing performance for libraries that support it, which processes data sequentially and is memory-efficient for large files.
357
+ Benchmark configuration files control what tests to run and how to run them.
345
358
 
346
- === Memory usage analysis
359
+ .Short configuration (CI-friendly) (`config/benchmarks/short.yml`)
360
+ [source,yaml]
361
+ ----
362
+ name: short-benchmark
347
363
 
348
- Profiles memory allocation and retention during serialization operations using the `memory_profiler` gem.
364
+ data_sizes:
365
+ - small
349
366
 
350
- == Output and reports
367
+ formats:
368
+ - xml
369
+ - json
370
+ - yaml
371
+ - toml
351
372
 
352
- === Generated files
373
+ iterations:
374
+ small: 5
375
+ medium: 2
376
+ large: 1
353
377
 
354
- Running benchmarks creates the following output structure:
378
+ operations:
379
+ - parse
380
+ - generate
381
+ - streaming
355
382
 
356
- [source]
383
+ warmup: 2
357
384
  ----
358
- results/
359
- ├── reports/
360
- │ ├── benchmark_report.html # Main HTML report
361
- │ └── benchmark_report.adoc # AsciiDoc source
362
- ├── charts/
363
- │ ├── parsing_performance.svg
364
- │ ├── generation_performance.svg
365
- │ ├── streaming_performance.svg
366
- │ ├── memory_usage_comparison.svg
367
- │ └── format_comparison.svg
368
- ├── data/
369
- │ ├── results.json # Raw benchmark data
370
- │ └── results.csv # CSV export
371
- └── assets/
372
- └── css/
373
- └── benchmark_report.css # Report styling
374
- ----
375
-
376
- === Report features
377
-
378
- * **Multi-format comparison**: Compare XML, JSON, and TOML performance
379
- * **Interactive charts**: SVG-based performance visualizations
380
- * **Comparative analysis**: Side-by-side library comparisons
381
- * **Performance rankings**: Fastest to slowest for each category
382
- * **Memory profiling**: Detailed memory allocation analysis
383
- * **Feature matrix**: Capability comparison across libraries
384
- * **Recommendations**: Use-case specific library suggestions
385
- * **Environment details**: Ruby version, platform, and library versions
386
-
387
- === Sample output
388
385
 
389
- [source]
386
+ .Full configuration (Comprehensive) (`config/benchmarks/full.yml`)
387
+ [source,yaml]
390
388
  ----
391
- Serialbench - Comprehensive Serialization Performance Tests
392
- ===========================================================
393
- Environment: Ruby 3.3.2 on arm64-darwin23
394
- Timestamp: 2024-01-15T10:30:00Z
395
-
396
- Available serializers: rexml, json, oj, toml-rb
397
- Test formats: xml, json, toml
398
- Test data sizes: small, medium, large
389
+ name: full-benchmark
399
390
 
400
- Parsing Performance:
401
- Small files:
402
- JSON/oj: 0.08ms
403
- JSON/json: 0.12ms
404
- XML/rexml: 0.45ms
405
- TOML/toml-rb: 0.52ms
391
+ data_sizes:
392
+ - small
393
+ - medium
394
+ - large
406
395
 
407
- Medium files:
408
- JSON/oj: 8.23ms
409
- JSON/json: 12.67ms
410
- XML/rexml: 28.45ms
411
- TOML/toml-rb: 35.21ms
412
- ----
396
+ formats:
397
+ - xml
398
+ - json
399
+ - yaml
400
+ - toml
413
401
 
414
- == Methodology
402
+ iterations:
403
+ small: 20
404
+ medium: 5
405
+ large: 2
415
406
 
416
- === Performance measurement
407
+ operations:
408
+ - parse
409
+ - generate
410
+ - streaming
411
+ - memory
417
412
 
418
- * Each test runs multiple iterations with warmup iterations
419
- * Memory profiling uses 10 iterations to reduce noise
420
- * Results show average performance across all iterations
421
- * Benchmarks use Ruby's `Benchmark.realtime` for precise timing
413
+ warmup: 3
414
+ ----
422
415
 
423
- === Test data
416
+ == Results structure
424
417
 
425
- ==== Synthetic datasets
418
+ === Individual run results
426
419
 
427
- The benchmark suite uses carefully crafted synthetic data that represents common real-world scenarios:
420
+ Results are stored in a structured directory format, with each run containing
421
+ raw benchmark data and execution logs.
428
422
 
429
- * **Configuration files**: Small, nested structures typical of application settings
430
- * **API responses**: Medium-sized documents with repeated record structures
431
- * **Data exports**: Large documents with extensive hierarchical data
423
+ The directory is located at `results/runs/{name}/`, where `{name}` is the name
424
+ of the environment used for the benchmark.
432
425
 
433
- ==== Multi-format consistency
426
+ [source]
427
+ ----
428
+ results/runs/docker-ruby-33-results/
429
+ ├── results.yaml # Raw benchmark data
430
+ └── benchmark.log # Execution log
431
+ ----
434
432
 
435
- * Equivalent data structures across XML, JSON, and TOML formats
436
- * Consistent complexity and nesting levels
437
- * Representative of real-world usage patterns
433
+ === ResultSet structure
438
434
 
439
- === Statistical considerations
435
+ ResultSets aggregate multiple benchmark runs for comparison. They are stored in
436
+ a structured directory format at `results/sets/{name}/`, where `{name}` is the
437
+ name of the result set.
440
438
 
441
- * Multiple iterations reduce timing variance
442
- * Warmup iterations eliminate JIT compilation effects
443
- * Memory measurements account for garbage collection
444
- * Results include both absolute and relative performance metrics
439
+ [source]
440
+ ----
441
+ results/sets/ruby-version-comparison/
442
+ └── resultset.yml # Result set configuration
443
+ ----
445
444
 
446
- == Library comparison matrix
445
+ == Benchmark categories
447
446
 
448
- [cols="1,1,1,1,1,1,1"]
449
- |===
450
- |Format |Library |Parsing |Generation |Streaming |Memory |Features
451
-
452
- |XML |REXML |⭐⭐ |⭐⭐ |⭐⭐⭐ |⭐⭐ |Built-in
453
- |XML |Ox |⭐⭐⭐⭐⭐ |⭐⭐⭐⭐⭐ |⭐⭐⭐⭐ |⭐⭐⭐⭐⭐ |High-performance
454
- |XML |Nokogiri |⭐⭐⭐⭐ |⭐⭐⭐⭐ |⭐⭐⭐⭐ |⭐⭐⭐⭐ |Feature-rich
455
- |XML |LibXML |⭐⭐⭐⭐⭐ |⭐⭐⭐⭐ |⭐⭐⭐⭐ |⭐⭐⭐⭐⭐ |High-performance
456
- |XML |Oga |⭐⭐ |⭐⭐ |⭐⭐⭐ |⭐⭐ |Pure Ruby
457
- |JSON |JSON |⭐⭐⭐ |⭐⭐⭐ |❌ |⭐⭐⭐ |Built-in
458
- |JSON |Oj |⭐⭐⭐⭐⭐ |⭐⭐⭐⭐⭐ |⭐⭐⭐⭐ |⭐⭐⭐⭐⭐ |High-performance
459
- |JSON |YAJL |⭐⭐⭐⭐ |⭐⭐⭐ |⭐⭐⭐⭐ |⭐⭐⭐⭐ |Streaming
460
- |TOML |TOML-RB |⭐⭐⭐ |⭐⭐⭐ |❌ |⭐⭐⭐ |Standard
461
- |TOML |Tomlib |⭐⭐⭐⭐⭐ |⭐⭐⭐⭐ |❌ |⭐⭐⭐⭐⭐ |High-performance
462
- |===
447
+ === Parsing performance
463
448
 
464
- _Performance ratings: ⭐⭐⭐⭐⭐ Excellent, ⭐⭐⭐⭐ Good, ⭐⭐⭐ Average, ⭐⭐ Below average, ⭐ Poor, ❌ Not supported_
449
+ Measures the time required to parse serialized data into Ruby objects.
465
450
 
466
- == Recommendations
451
+ * **Small files**: ~1KB configuration-style documents
452
+ * **Medium files**: ~1MB API responses with 1,000 records
453
+ * **Large files**: ~10MB data exports with 10,000 records
467
454
 
468
- === For high-performance JSON applications
455
+ === Generation performance
469
456
 
470
- **Oj** is recommended for applications where JSON parsing/generation speed is critical. It consistently outperforms the built-in JSON library.
457
+ Tests how quickly libraries can convert Ruby objects into serialized strings.
471
458
 
472
- === For configuration files
459
+ === Streaming performance
473
460
 
474
- **TOML** provides human-readable configuration with good parsing performance. **JSON** is faster but less readable for configuration.
461
+ Evaluates streaming event-based parsing performance for libraries that support
462
+ it, which processes data sequentially and is memory-efficient for large files.
475
463
 
476
- === For data interchange
464
+ === Memory usage analysis
477
465
 
478
- **JSON** offers the best balance of performance, compatibility, and tooling support across different systems.
466
+ Profiles memory allocation and retention during serialization operations using
467
+ the `memory_profiler` gem.
479
468
 
480
- === For document processing
469
+ == Interactive Dashboard Features
481
470
 
482
- **XML** with **REXML** provides built-in support, though performance is lower than JSON alternatives.
471
+ The generated HTML sites provide comprehensive interactive dashboards with:
483
472
 
484
- === For memory-constrained environments
473
+ === Navigation and Filtering
474
+ * **Format tabs**: Dedicated views for XML, JSON, YAML, and TOML
475
+ * **Operation sections**: Parsing, generation, streaming, and memory usage
476
+ * **Dynamic filtering**: Platform, Ruby version, and environment selection
477
+ * **Real-time updates**: Charts update instantly based on filter selections
485
478
 
486
- **Oj** demonstrates superior memory efficiency. For large file processing, streaming approaches are recommended where available.
479
+ === Visualization Capabilities
480
+ * **Chart.js integration**: Interactive performance charts with hover details
481
+ * **Multi-scale handling**: Automatic Y-axis scaling for different performance ranges
482
+ * **Color-coded data**: Consistent color schemes across serializers and environments
483
+ * **Responsive design**: Optimized for desktop and mobile viewing
487
484
 
488
- === For minimal dependencies
485
+ === User Experience
486
+ * **Theme toggle**: Light and dark mode with persistent preferences
487
+ * **Keyboard navigation**: Full accessibility support
488
+ * **Fast loading**: Optimized JavaScript for quick dashboard initialization
489
+ * **Export capabilities**: JSON data export for further analysis
489
490
 
490
- **JSON** and **REXML** are included with Ruby and require no additional gems, making them suitable for environments with strict dependency constraints.
491
491
 
492
492
  == Development
493
493
 
494
- === Running tests
494
+ === Running Tests
495
495
 
496
- [source,shell]
496
+ [source]
497
497
  ----
498
498
  $ bundle exec rake
499
499
  $ bundle exec rspec
500
500
  ----
501
501
 
502
- === Contributing
502
+ === Adding a new serializers
503
503
 
504
- 1. Fork the repository
505
- 2. Create your feature branch (`git checkout -b feature/my-new-feature`)
506
- 3. Commit your changes (`git commit -am 'Add some feature'`)
507
- 4. Push to the branch (`git push origin feature/my-new-feature`)
508
- 5. Create a new Pull Request
504
+ To add support for additional serialization libraries:
509
505
 
510
- === Adding new serializers
506
+ . Create a new serializer class in `lib/serialbench/serializers/{format}/`
507
+ . Inherit from the appropriate base class (`BaseXmlSerializer`, `BaseJsonSerializer`, etc.)
508
+ . Implement the required methods: `parse`, `generate`, `name`, `version`
509
+ . Add the serializer to the registry in `lib/serialbench/serializers.rb`
510
+ . Update documentation and tests
511
511
 
512
- To add support for additional serialization libraries:
512
+ === Contributing
513
513
 
514
- 1. Create a new serializer class in `lib/serialbench/serializers/{format}/`
515
- 2. Inherit from the appropriate base class (`BaseXmlSerializer`, `BaseJsonSerializer`, etc.)
516
- 3. Implement the required methods: `parse`, `generate`, `name`, `version`
517
- 4. Add the serializer to the registry in `lib/serialbench/serializers.rb`
518
- 5. Update documentation and tests
514
+ . Fork the repository
515
+ . Create your feature branch (`git checkout -b feature/my-new-feature`)
516
+ . Commit your changes (`git commit -am 'Add some feature'`)
517
+ . Push to the branch (`git push origin feature/my-new-feature`)
518
+ . Create a new Pull Request
519
519
 
520
- ==== Example: Adding a new JSON serializer
521
520
 
522
- [source,ruby]
523
- ----
524
- # lib/serialbench/serializers/json/yajl_serializer.rb
525
- class YajlSerializer < BaseJsonSerializer
526
- def available?
527
- require_library('yajl')
528
- end
521
+ == Known issues
529
522
 
530
- def name
531
- 'yajl'
532
- end
523
+ === Syck YAML serializer segmentation faults
533
524
 
534
- def version
535
- require 'yajl'
536
- Yajl::VERSION
537
- end
525
+ The Syck YAML serializer at version 1.5+ is known to cause segmentation faults
526
+ on Ruby 3.1 and later versions. Serialbench automatically detects this
527
+ problematic configuration and:
538
528
 
539
- def parse(json_string)
540
- require 'yajl'
541
- Yajl::Parser.parse(json_string)
542
- end
529
+ * Displays a warning message when Syck is detected on Ruby 3.1+
530
+ * Skips Syck benchmarks to prevent crashes
531
+ * Continues with other YAML serializers (Psych)
543
532
 
544
- def generate(object, options = {})
545
- require 'yajl'
546
- Yajl::Encoder.encode(object)
547
- end
548
- end
549
- ----
533
+ === Syck overrides YAML constant
550
534
 
551
- == Architecture
535
+ On occasion after Syck is loaded, the constant `YAML` may be redefined to
536
+ `Syck`, which can cause issues in other parts of the codebase. This can cause
537
+ YAML output to fail when using libraries that expect `YAML` to have the
538
+ `Psych` API.
552
539
 
553
- === Serializer hierarchy
540
+ In `benchmark_cli.rb` there is therefore such code to ensure that
541
+ `YAML` is defined as `Psych` when writing to file is needed:
554
542
 
555
- [source]
543
+ [source,ruby]
556
544
  ----
557
- BaseSerializer
558
- ├── BaseXmlSerializer
559
- │ └── RexmlSerializer
560
- ├── BaseJsonSerializer
561
- │ ├── JsonSerializer
562
- │ └── OjSerializer
563
- └── BaseTomlSerializer
564
- └── TomlRbSerializer
545
+ # Restore YAML to use Psych for output, otherwise lutaml-model's to_yaml
546
+ # will have no output
547
+ Object.const_set(:YAML, Psych)
565
548
  ----
566
549
 
567
- === Key components
568
-
569
- * **Serializers**: Individual library implementations
570
- * **BenchmarkRunner**: Orchestrates benchmark execution
571
- * **ResultFormatter**: Formats and displays results
572
- * **ReportGenerator**: Creates HTML/AsciiDoc reports
573
- * **ChartGenerator**: Creates performance visualizations
574
- * **MemoryProfiler**: Analyzes memory usage patterns
575
-
576
- == Research and references
577
-
578
- This benchmarking suite was developed based on research from:
579
-
580
- * https://www.ohler.com/dev/xml_with_ruby/xml_with_ruby.html[XML with Ruby performance analysis]
581
- * https://gist.github.com/danneu/3977120[Ruby XML parser comparison]
582
- * https://gist.github.com/adilosa/d4277dc1c683da91990515352ffe5420[XML parsing benchmarks]
583
550
 
584
- == Copyright
551
+ == License and copyright
585
552
 
586
- This gem is developed, maintained and funded by
587
- https://www.ribose.com[Ribose Inc.]
553
+ Copyright Ribose.
588
554
 
589
- == License
555
+ This gem is developed, maintained and funded by https://www.ribose.com[Ribose]
590
556
 
591
557
  The gem is available as open source under the terms of the
592
558
  https://opensource.org/licenses/BSD-2-Clause[2-Clause BSD License].