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.
- checksums.yaml +4 -4
- data/.github/workflows/benchmark.yml +181 -30
- data/.github/workflows/ci.yml +3 -3
- data/.github/workflows/docker.yml +272 -0
- data/.github/workflows/rake.yml +15 -0
- data/.github/workflows/release.yml +25 -0
- data/Gemfile +6 -30
- data/README.adoc +381 -415
- data/Rakefile +0 -55
- data/config/benchmarks/full.yml +29 -0
- data/config/benchmarks/short.yml +26 -0
- data/config/environments/asdf-ruby-3.2.yml +8 -0
- data/config/environments/asdf-ruby-3.3.yml +8 -0
- data/config/environments/docker-ruby-3.0.yml +9 -0
- data/config/environments/docker-ruby-3.1.yml +9 -0
- data/config/environments/docker-ruby-3.2.yml +9 -0
- data/config/environments/docker-ruby-3.3.yml +9 -0
- data/config/environments/docker-ruby-3.4.yml +9 -0
- data/docker/Dockerfile.alpine +33 -0
- data/docker/Dockerfile.ubuntu +32 -0
- data/docker/README.md +214 -0
- data/exe/serialbench +1 -1
- data/lib/serialbench/benchmark_runner.rb +270 -350
- data/lib/serialbench/cli/base_cli.rb +51 -0
- data/lib/serialbench/cli/benchmark_cli.rb +380 -0
- data/lib/serialbench/cli/environment_cli.rb +181 -0
- data/lib/serialbench/cli/resultset_cli.rb +215 -0
- data/lib/serialbench/cli/ruby_build_cli.rb +238 -0
- data/lib/serialbench/cli.rb +59 -410
- data/lib/serialbench/config_manager.rb +140 -0
- data/lib/serialbench/models/benchmark_config.rb +63 -0
- data/lib/serialbench/models/benchmark_result.rb +45 -0
- data/lib/serialbench/models/environment_config.rb +71 -0
- data/lib/serialbench/models/platform.rb +59 -0
- data/lib/serialbench/models/result.rb +53 -0
- data/lib/serialbench/models/result_set.rb +71 -0
- data/lib/serialbench/models/result_store.rb +108 -0
- data/lib/serialbench/models.rb +54 -0
- data/lib/serialbench/ruby_build_manager.rb +153 -0
- data/lib/serialbench/runners/asdf_runner.rb +296 -0
- data/lib/serialbench/runners/base.rb +32 -0
- data/lib/serialbench/runners/docker_runner.rb +142 -0
- data/lib/serialbench/serializers/base_serializer.rb +8 -16
- data/lib/serialbench/serializers/json/base_json_serializer.rb +4 -4
- data/lib/serialbench/serializers/json/json_serializer.rb +0 -2
- data/lib/serialbench/serializers/json/oj_serializer.rb +0 -2
- data/lib/serialbench/serializers/json/rapidjson_serializer.rb +50 -0
- data/lib/serialbench/serializers/json/yajl_serializer.rb +6 -4
- data/lib/serialbench/serializers/toml/base_toml_serializer.rb +5 -3
- data/lib/serialbench/serializers/toml/toml_rb_serializer.rb +0 -2
- data/lib/serialbench/serializers/toml/tomlib_serializer.rb +0 -2
- data/lib/serialbench/serializers/toml/tomlrb_serializer.rb +56 -0
- data/lib/serialbench/serializers/xml/base_xml_serializer.rb +4 -9
- data/lib/serialbench/serializers/xml/libxml_serializer.rb +0 -2
- data/lib/serialbench/serializers/xml/nokogiri_serializer.rb +21 -5
- data/lib/serialbench/serializers/xml/oga_serializer.rb +0 -2
- data/lib/serialbench/serializers/xml/ox_serializer.rb +0 -2
- data/lib/serialbench/serializers/xml/rexml_serializer.rb +32 -4
- data/lib/serialbench/serializers/yaml/base_yaml_serializer.rb +59 -0
- data/lib/serialbench/serializers/yaml/psych_serializer.rb +54 -0
- data/lib/serialbench/serializers/yaml/syck_serializer.rb +102 -0
- data/lib/serialbench/serializers.rb +34 -6
- data/lib/serialbench/site_generator.rb +105 -0
- data/lib/serialbench/templates/assets/css/benchmark_report.css +535 -0
- data/lib/serialbench/templates/assets/css/format_based.css +526 -0
- data/lib/serialbench/templates/assets/css/themes.css +588 -0
- data/lib/serialbench/templates/assets/js/chart_helpers.js +381 -0
- data/lib/serialbench/templates/assets/js/dashboard.js +796 -0
- data/lib/serialbench/templates/assets/js/navigation.js +142 -0
- data/lib/serialbench/templates/base.liquid +49 -0
- data/lib/serialbench/templates/format_based.liquid +279 -0
- data/lib/serialbench/templates/partials/chart_section.liquid +4 -0
- data/lib/serialbench/version.rb +1 -1
- data/lib/serialbench.rb +2 -31
- data/serialbench.gemspec +28 -17
- metadata +192 -55
- data/lib/serialbench/chart_generator.rb +0 -821
- data/lib/serialbench/result_formatter.rb +0 -182
- data/lib/serialbench/result_merger.rb +0 -1201
- data/lib/serialbench/serializers/xml/base_parser.rb +0 -69
- data/lib/serialbench/serializers/xml/libxml_parser.rb +0 -98
- data/lib/serialbench/serializers/xml/nokogiri_parser.rb +0 -111
- data/lib/serialbench/serializers/xml/oga_parser.rb +0 -85
- data/lib/serialbench/serializers/xml/ox_parser.rb +0 -64
- data/lib/serialbench/serializers/xml/rexml_parser.rb +0 -129
data/README.adoc
CHANGED
@@ -1,592 +1,558 @@
|
|
1
|
-
= Serialbench:
|
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/
|
5
|
-
image:https://
|
6
|
-
image:https://img.shields.io/github/
|
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
|
-
==
|
8
|
+
== Overview
|
9
9
|
|
10
|
-
Serialbench is a comprehensive benchmarking suite that evaluates the performance of popular Ruby serialization libraries across multiple formats and
|
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
|
-
|
12
|
+
**Supported Formats**: XML, JSON, YAML, TOML, and more
|
13
13
|
|
14
|
-
|
14
|
+
**Key Metrics**: Parsing speed, generation speed, memory usage, streaming capabilities, and feature completeness
|
15
15
|
|
16
|
-
|
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
|
-
|
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
|
-
|
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
|
-
|
89
|
+
|===
|
33
90
|
|
34
|
-
[source,ruby]
|
35
|
-
----
|
36
|
-
gem 'serialbench'
|
37
|
-
----
|
38
91
|
|
39
|
-
|
92
|
+
== Data formats and schema
|
40
93
|
|
41
|
-
|
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
|
-
|
97
|
+
The data formats include:
|
47
98
|
|
48
|
-
|
49
|
-
|
50
|
-
|
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
|
-
|
104
|
+
== Prerequisites
|
54
105
|
|
55
|
-
|
106
|
+
=== System requirements
|
56
107
|
|
57
|
-
|
58
|
-
|
59
|
-
|
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
|
-
|
63
|
-
$ gem install oj toml-rb
|
112
|
+
=== Library dependencies
|
64
113
|
|
65
|
-
|
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
|
-
|
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
|
-
|
107
|
-
|
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
|
-
==
|
114
|
-
|
115
|
-
=== Command line interface
|
128
|
+
== Installation
|
116
129
|
|
117
|
-
|
130
|
+
Add this line to your application's Gemfile:
|
118
131
|
|
119
|
-
[source,
|
132
|
+
[source,ruby]
|
120
133
|
----
|
121
|
-
|
134
|
+
gem 'serialbench'
|
122
135
|
----
|
123
136
|
|
124
|
-
|
137
|
+
And then execute:
|
125
138
|
|
126
|
-
[source
|
139
|
+
[source]
|
127
140
|
----
|
128
|
-
$
|
141
|
+
$ bundle install
|
129
142
|
----
|
130
143
|
|
131
|
-
|
144
|
+
Or install it yourself as:
|
132
145
|
|
133
|
-
[source
|
146
|
+
[source]
|
134
147
|
----
|
135
|
-
$
|
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
|
-
|
152
|
+
== Command line interface
|
147
153
|
|
148
|
-
|
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
|
-
|
157
|
+
=== Main Commands Overview
|
154
158
|
|
155
|
-
[source,
|
159
|
+
[source,sh]
|
156
160
|
----
|
157
|
-
$ serialbench
|
158
|
-
|
159
|
-
|
160
|
-
Output results in JSON format only:
|
161
|
+
$ serialbench
|
162
|
+
Serialbench - Benchmarking Framework for Ruby Serialization Libraries
|
161
163
|
|
162
|
-
|
163
|
-
|
164
|
-
$ serialbench benchmark --output-format json
|
165
|
-
----
|
164
|
+
USAGE:
|
165
|
+
serialbench COMMAND [SUBCOMMAND] [OPTIONS]
|
166
166
|
|
167
|
-
|
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
|
-
|
170
|
-
|
171
|
-
|
172
|
-
$ serialbench list --format xml
|
173
|
-
----
|
175
|
+
EXAMPLES:
|
176
|
+
# Create a Docker environment
|
177
|
+
serialbench environment new docker-test docker
|
174
178
|
|
175
|
-
|
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
|
-
|
178
|
-
|
179
|
-
|
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
|
-
|
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
|
-
|
186
|
-
|
187
|
-
|
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
|
-
===
|
196
|
+
=== Environment management
|
191
197
|
|
192
|
-
|
198
|
+
The `environment` subcommand manages environment configurations and executes
|
199
|
+
benchmarks across different Ruby environments.
|
193
200
|
|
194
|
-
[source
|
201
|
+
[source]
|
195
202
|
----
|
196
|
-
$ serialbench
|
197
|
-
|
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
|
-
|
203
|
-
----
|
204
|
-
$ serialbench benchmark --formats xml --memory-profiling
|
205
|
-
----
|
212
|
+
=== Benchmark management
|
206
213
|
|
207
|
-
|
214
|
+
The `benchmark` subcommand handles individual benchmark runs and site generation.
|
208
215
|
|
209
|
-
[source
|
216
|
+
[source]
|
210
217
|
----
|
211
|
-
$ serialbench benchmark
|
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
|
-
|
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
|
-
|
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
|
-
|
234
|
+
The `resultset` subcommand manages collections of benchmark runs for comparison analysis.
|
224
235
|
|
225
|
-
[source
|
236
|
+
[source]
|
226
237
|
----
|
227
|
-
$ serialbench
|
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
|
-
|
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
|
-
|
251
|
+
The `ruby-build` subcommand manages Ruby build definitions and version information.
|
238
252
|
|
239
|
-
|
253
|
+
Serialbench uses ruby-build definitions of Ruby interpreter types and versions
|
254
|
+
for identification.
|
240
255
|
|
241
|
-
[source
|
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
|
-
|
252
|
-
report_files = Serialbench.generate_reports(results)
|
270
|
+
== Workflow examples
|
253
271
|
|
254
|
-
|
255
|
-
puts "Charts generated: #{report_files[:charts].length}"
|
256
|
-
----
|
272
|
+
=== Docker-based testing
|
257
273
|
|
258
|
-
|
274
|
+
NOTE: This works.
|
259
275
|
|
260
|
-
[source,
|
276
|
+
[source,bash]
|
261
277
|
----
|
262
|
-
|
278
|
+
# 1. Prepare Docker environment
|
279
|
+
$ bundle exec serialbench environment prepare config/environments/docker-ruby-3.1.yml
|
263
280
|
|
264
|
-
#
|
265
|
-
|
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
|
-
#
|
268
|
-
|
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
|
-
#
|
273
|
-
|
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
|
-
|
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
|
-
|
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
|
-
|
284
|
-
oj_serializer = Serialbench::Serializers::Json::OjSerializer.new
|
300
|
+
=== ASDF-based testing
|
285
301
|
|
286
|
-
|
287
|
-
json_content = '{"users": [{"name": "Alice", "age": 30}]}'
|
302
|
+
WARNING: THIS IS NOT YET WORKING.
|
288
303
|
|
289
|
-
|
290
|
-
|
304
|
+
[source,bash]
|
305
|
+
----
|
306
|
+
# 1. Validate configuration
|
307
|
+
$ bundle exec serialbench benchmark validate serialbench-asdf.yml
|
291
308
|
|
292
|
-
|
293
|
-
|
309
|
+
# 2. Prepare Ruby environments
|
310
|
+
$ bundle exec serialbench benchmark prepare asdf --config=serialbench-asdf.yml
|
294
311
|
|
295
|
-
|
296
|
-
|
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
|
-
|
303
|
-
|
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
|
-
==
|
322
|
+
== Configuration Files
|
329
323
|
|
330
|
-
===
|
324
|
+
=== Environment configuration
|
331
325
|
|
332
|
-
|
326
|
+
Environment configuration files define how benchmarks are executed in different runtime environments.
|
333
327
|
|
334
|
-
|
335
|
-
|
336
|
-
|
337
|
-
|
338
|
-
|
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
|
-
|
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
|
-
===
|
355
|
+
=== Benchmark configuration
|
343
356
|
|
344
|
-
|
357
|
+
Benchmark configuration files control what tests to run and how to run them.
|
345
358
|
|
346
|
-
|
359
|
+
.Short configuration (CI-friendly) (`config/benchmarks/short.yml`)
|
360
|
+
[source,yaml]
|
361
|
+
----
|
362
|
+
name: short-benchmark
|
347
363
|
|
348
|
-
|
364
|
+
data_sizes:
|
365
|
+
- small
|
349
366
|
|
350
|
-
|
367
|
+
formats:
|
368
|
+
- xml
|
369
|
+
- json
|
370
|
+
- yaml
|
371
|
+
- toml
|
351
372
|
|
352
|
-
|
373
|
+
iterations:
|
374
|
+
small: 5
|
375
|
+
medium: 2
|
376
|
+
large: 1
|
353
377
|
|
354
|
-
|
378
|
+
operations:
|
379
|
+
- parse
|
380
|
+
- generate
|
381
|
+
- streaming
|
355
382
|
|
356
|
-
|
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
|
-
|
386
|
+
.Full configuration (Comprehensive) (`config/benchmarks/full.yml`)
|
387
|
+
[source,yaml]
|
390
388
|
----
|
391
|
-
|
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
|
-
|
401
|
-
|
402
|
-
|
403
|
-
|
404
|
-
XML/rexml: 0.45ms
|
405
|
-
TOML/toml-rb: 0.52ms
|
391
|
+
data_sizes:
|
392
|
+
- small
|
393
|
+
- medium
|
394
|
+
- large
|
406
395
|
|
407
|
-
|
408
|
-
|
409
|
-
|
410
|
-
|
411
|
-
|
412
|
-
----
|
396
|
+
formats:
|
397
|
+
- xml
|
398
|
+
- json
|
399
|
+
- yaml
|
400
|
+
- toml
|
413
401
|
|
414
|
-
|
402
|
+
iterations:
|
403
|
+
small: 20
|
404
|
+
medium: 5
|
405
|
+
large: 2
|
415
406
|
|
416
|
-
|
407
|
+
operations:
|
408
|
+
- parse
|
409
|
+
- generate
|
410
|
+
- streaming
|
411
|
+
- memory
|
417
412
|
|
418
|
-
|
419
|
-
|
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
|
-
|
416
|
+
== Results structure
|
424
417
|
|
425
|
-
|
418
|
+
=== Individual run results
|
426
419
|
|
427
|
-
|
420
|
+
Results are stored in a structured directory format, with each run containing
|
421
|
+
raw benchmark data and execution logs.
|
428
422
|
|
429
|
-
|
430
|
-
|
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
|
-
|
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
|
-
|
436
|
-
* Consistent complexity and nesting levels
|
437
|
-
* Representative of real-world usage patterns
|
433
|
+
=== ResultSet structure
|
438
434
|
|
439
|
-
|
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
|
-
|
442
|
-
|
443
|
-
|
444
|
-
|
439
|
+
[source]
|
440
|
+
----
|
441
|
+
results/sets/ruby-version-comparison/
|
442
|
+
└── resultset.yml # Result set configuration
|
443
|
+
----
|
445
444
|
|
446
|
-
==
|
445
|
+
== Benchmark categories
|
447
446
|
|
448
|
-
|
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
|
-
|
449
|
+
Measures the time required to parse serialized data into Ruby objects.
|
465
450
|
|
466
|
-
|
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
|
-
===
|
455
|
+
=== Generation performance
|
469
456
|
|
470
|
-
|
457
|
+
Tests how quickly libraries can convert Ruby objects into serialized strings.
|
471
458
|
|
472
|
-
===
|
459
|
+
=== Streaming performance
|
473
460
|
|
474
|
-
|
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
|
-
===
|
464
|
+
=== Memory usage analysis
|
477
465
|
|
478
|
-
|
466
|
+
Profiles memory allocation and retention during serialization operations using
|
467
|
+
the `memory_profiler` gem.
|
479
468
|
|
480
|
-
|
469
|
+
== Interactive Dashboard Features
|
481
470
|
|
482
|
-
|
471
|
+
The generated HTML sites provide comprehensive interactive dashboards with:
|
483
472
|
|
484
|
-
===
|
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
|
-
|
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
|
-
===
|
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
|
494
|
+
=== Running Tests
|
495
495
|
|
496
|
-
[source
|
496
|
+
[source]
|
497
497
|
----
|
498
498
|
$ bundle exec rake
|
499
499
|
$ bundle exec rspec
|
500
500
|
----
|
501
501
|
|
502
|
-
===
|
502
|
+
=== Adding a new serializers
|
503
503
|
|
504
|
-
|
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
|
-
|
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
|
-
|
512
|
+
=== Contributing
|
513
513
|
|
514
|
-
|
515
|
-
|
516
|
-
|
517
|
-
|
518
|
-
|
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
|
-
|
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
|
-
|
531
|
-
'yajl'
|
532
|
-
end
|
523
|
+
=== Syck YAML serializer segmentation faults
|
533
524
|
|
534
|
-
|
535
|
-
|
536
|
-
|
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
|
-
|
540
|
-
|
541
|
-
|
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
|
-
|
545
|
-
require 'yajl'
|
546
|
-
Yajl::Encoder.encode(object)
|
547
|
-
end
|
548
|
-
end
|
549
|
-
----
|
533
|
+
=== Syck overrides YAML constant
|
550
534
|
|
551
|
-
|
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
|
-
|
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
|
-
|
558
|
-
|
559
|
-
|
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
|
-
==
|
551
|
+
== License and copyright
|
585
552
|
|
586
|
-
|
587
|
-
https://www.ribose.com[Ribose Inc.]
|
553
|
+
Copyright Ribose.
|
588
554
|
|
589
|
-
|
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].
|