serialbench 0.1.1 → 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 +13 -5
- data/.github/workflows/docker.yml +35 -9
- data/.github/workflows/rake.yml +15 -0
- data/Gemfile +2 -1
- data/README.adoc +267 -1129
- 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.benchmark → Dockerfile.ubuntu} +4 -3
- data/docker/README.md +2 -2
- data/exe/serialbench +1 -1
- data/lib/serialbench/benchmark_runner.rb +261 -423
- 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 +58 -601
- 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/yajl_serializer.rb +0 -2
- 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 +0 -2
- 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 +0 -2
- data/lib/serialbench/serializers/yaml/base_yaml_serializer.rb +5 -1
- data/lib/serialbench/serializers/yaml/syck_serializer.rb +59 -22
- data/lib/serialbench/serializers.rb +23 -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 +4 -1
- metadata +86 -16
- data/config/ci.yml +0 -22
- data/config/full.yml +0 -30
- data/docker/run-benchmarks.sh +0 -356
- 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
@@ -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
|
-
**
|
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,202 +80,49 @@ 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
|
+
| 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.)
|
88
|
+
|
83
89
|
|===
|
84
90
|
|
85
|
-
== Benchmark report JSON format
|
86
91
|
|
87
|
-
|
92
|
+
== Data formats and schema
|
88
93
|
|
89
|
-
|
94
|
+
Serialbench generates structured YAML output for benchmark results, with
|
95
|
+
different formats for single-environment and multi-environment runs.
|
90
96
|
|
91
|
-
|
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
|
-
----
|
97
|
+
The data formats include:
|
158
98
|
|
159
|
-
|
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
|
160
103
|
|
161
|
-
|
104
|
+
== Prerequisites
|
162
105
|
|
163
|
-
|
164
|
-
|
165
|
-
|
166
|
-
|
167
|
-
|
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
|
-
----
|
106
|
+
=== System requirements
|
107
|
+
|
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
|
214
111
|
|
215
|
-
===
|
112
|
+
=== Library dependencies
|
216
113
|
|
217
|
-
|
114
|
+
**System dependencies** (required for some native extensions):
|
218
115
|
|
219
|
-
[source,
|
116
|
+
[source,bash]
|
220
117
|
----
|
221
|
-
|
222
|
-
|
223
|
-
|
224
|
-
|
225
|
-
|
226
|
-
|
227
|
-
|
228
|
-
|
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
|
-
}
|
118
|
+
# macOS with Homebrew
|
119
|
+
$ brew install libxml2 libxslt
|
120
|
+
|
121
|
+
# Ubuntu/Debian
|
122
|
+
$ sudo apt-get install libxml2-dev libxslt1-dev build-essential
|
123
|
+
|
124
|
+
# CentOS/RHEL/Fedora
|
125
|
+
$ sudo yum install libxml2-devel libxslt-devel gcc gcc-c++
|
279
126
|
----
|
280
127
|
|
281
128
|
== Installation
|
@@ -301,900 +148,298 @@ Or install it yourself as:
|
|
301
148
|
$ gem install serialbench
|
302
149
|
----
|
303
150
|
|
304
|
-
=== XML library dependencies
|
305
|
-
|
306
|
-
To run benchmarks for all supported XML libraries, install the following gems:
|
307
151
|
|
152
|
+
== Command line interface
|
308
153
|
|
309
|
-
|
310
|
-
|
311
|
-
# Core XML libraries
|
312
|
-
$ gem install ox nokogiri libxml-ruby oga
|
154
|
+
Serialbench provides a comprehensive Thor-based CLI with four main subcommands
|
155
|
+
for managing environments, benchmarks, result sets, and Ruby builds.
|
313
156
|
|
314
|
-
|
315
|
-
$ gem install oj toml-rb
|
157
|
+
=== Main Commands Overview
|
316
158
|
|
317
|
-
|
318
|
-
$ gem install memory_profiler
|
159
|
+
[source,sh]
|
319
160
|
----
|
161
|
+
$ serialbench
|
162
|
+
Serialbench - Benchmarking Framework for Ruby Serialization Libraries
|
320
163
|
|
164
|
+
USAGE:
|
165
|
+
serialbench COMMAND [SUBCOMMAND] [OPTIONS]
|
321
166
|
|
322
|
-
|
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
|
323
174
|
|
324
|
-
|
175
|
+
EXAMPLES:
|
176
|
+
# Create a Docker environment
|
177
|
+
serialbench environment new docker-test docker
|
325
178
|
|
326
|
-
|
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
|
327
182
|
|
328
|
-
|
183
|
+
# Create and execute a benchmark
|
184
|
+
serialbench benchmark create my-benchmark
|
185
|
+
serialbench benchmark execute my-benchmark.yml
|
329
186
|
|
330
|
-
|
331
|
-
|
332
|
-
|
333
|
-
----
|
334
|
-
|
335
|
-
==== Nokogiri
|
187
|
+
# Create a result set for comparison
|
188
|
+
serialbench resultset create comparison-set
|
189
|
+
serialbench resultset add-result comparison-set results/my-benchmark
|
336
190
|
|
337
|
-
|
338
|
-
|
339
|
-
|
191
|
+
# Generate static sites
|
192
|
+
serialbench benchmark build-site results/my-benchmark
|
193
|
+
serialbench resultset build-site resultsets/comparison-set
|
340
194
|
----
|
341
|
-
# macOS with Homebrew
|
342
|
-
$ 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
195
|
|
360
|
-
|
361
|
-
$ sudo apt-get install libxml2-dev
|
362
|
-
$ gem install libxml-ruby
|
363
|
-
----
|
364
|
-
|
365
|
-
==== Oga
|
196
|
+
=== Environment management
|
366
197
|
|
367
|
-
|
198
|
+
The `environment` subcommand manages environment configurations and executes
|
199
|
+
benchmarks across different Ruby environments.
|
368
200
|
|
369
201
|
[source]
|
370
202
|
----
|
371
|
-
$
|
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
|
372
209
|
----
|
373
210
|
|
374
|
-
== Docker containers and cross-platform benchmarking
|
375
|
-
|
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.
|
377
|
-
|
378
|
-
=== Published Docker containers
|
379
|
-
|
380
|
-
We publish multi-architecture Docker containers for all supported Ruby versions:
|
381
211
|
|
382
|
-
|
212
|
+
=== Benchmark management
|
383
213
|
|
384
|
-
|
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)
|
416
|
-
|
417
|
-
[source,bash]
|
418
|
-
----
|
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
|
444
|
-
|
445
|
-
# View results
|
446
|
-
ls -la results/
|
447
|
-
----
|
448
|
-
|
449
|
-
=== Multi-Ruby version comparison
|
450
|
-
|
451
|
-
Run benchmarks across all supported Ruby versions:
|
452
|
-
|
453
|
-
==== Windows (PowerShell)
|
454
|
-
|
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
|
488
|
-
|
489
|
-
Run benchmarks with custom parameters:
|
490
|
-
|
491
|
-
[source,bash]
|
492
|
-
----
|
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
|
508
|
-
----
|
509
|
-
|
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
|
214
|
+
The `benchmark` subcommand handles individual benchmark runs and site generation.
|
518
215
|
|
519
216
|
[source]
|
520
217
|
----
|
521
|
-
|
522
|
-
|
523
|
-
|
524
|
-
#
|
525
|
-
|
526
|
-
|
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
|
527
226
|
----
|
528
227
|
|
529
|
-
|
228
|
+
The `_docker_execute` command is a private command used internally by the
|
229
|
+
`execute` command to run benchmarks in Docker environments.
|
530
230
|
|
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
231
|
|
536
|
-
|
232
|
+
=== Result set management
|
537
233
|
|
538
|
-
|
234
|
+
The `resultset` subcommand manages collections of benchmark runs for comparison analysis.
|
539
235
|
|
540
236
|
[source]
|
541
237
|
----
|
542
|
-
|
543
|
-
|
544
|
-
|
545
|
-
|
546
|
-
|
547
|
-
|
548
|
-
|
549
|
-
|
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
|
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
|
561
246
|
----
|
562
247
|
|
563
|
-
=== Manual Docker usage
|
564
248
|
|
565
|
-
|
249
|
+
=== ruby-build management
|
566
250
|
|
567
|
-
|
568
|
-
----
|
569
|
-
$ docker build \
|
570
|
-
--build-arg RUBY_VERSION=3.3 \
|
571
|
-
-t serialbench:ruby-3.3 \
|
572
|
-
-f docker/Dockerfile.benchmark \
|
573
|
-
.
|
574
|
-
----
|
575
|
-
|
576
|
-
==== Run benchmarks in container
|
577
|
-
|
578
|
-
[source]
|
579
|
-
----
|
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
|
591
|
-
|
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
|
-
----
|
602
|
-
|
603
|
-
=== Supported Ruby versions
|
604
|
-
|
605
|
-
The Docker setup supports the following Ruby versions:
|
606
|
-
|
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:
|
251
|
+
The `ruby-build` subcommand manages Ruby build definitions and version information.
|
634
252
|
|
635
|
-
|
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
|
-
----
|
646
|
-
|
647
|
-
==== GitHub Pages generation
|
648
|
-
|
649
|
-
Generate interactive HTML reports ready for GitHub Pages deployment:
|
650
|
-
|
651
|
-
[source]
|
652
|
-
----
|
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
|
-
|
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
|
253
|
+
Serialbench uses ruby-build definitions of Ruby interpreter types and versions
|
254
|
+
for identification.
|
670
255
|
|
671
|
-
==== Deploying to GitHub Pages
|
672
|
-
|
673
|
-
. **Commit the generated files**:
|
674
|
-
+
|
675
256
|
[source]
|
676
257
|
----
|
677
|
-
$
|
678
|
-
|
679
|
-
|
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
|
680
267
|
----
|
681
268
|
|
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
|
-
|
690
|
-
=== Troubleshooting Docker issues
|
691
269
|
|
692
|
-
|
270
|
+
== Workflow examples
|
693
271
|
|
694
|
-
|
272
|
+
=== Docker-based testing
|
695
273
|
|
696
|
-
|
697
|
-
----
|
698
|
-
$ cat docker-results/build-ruby-3.3.log
|
699
|
-
----
|
274
|
+
NOTE: This works.
|
700
275
|
|
701
|
-
|
702
|
-
|
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
|
-
|
707
|
-
==== Runtime failures
|
708
|
-
|
709
|
-
Check benchmark execution logs:
|
710
|
-
|
711
|
-
[source]
|
712
|
-
----
|
713
|
-
$ cat docker-results/ruby-3.3/benchmark.log
|
276
|
+
[source,bash]
|
714
277
|
----
|
278
|
+
# 1. Prepare Docker environment
|
279
|
+
$ bundle exec serialbench environment prepare config/environments/docker-ruby-3.1.yml
|
715
280
|
|
716
|
-
|
717
|
-
|
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
|
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
|
721
283
|
|
722
|
-
|
284
|
+
# 3. Create a resultset
|
285
|
+
$ bundle exec serialbench resultset create docker-comparison results/sets/docker-comparison
|
723
286
|
|
724
|
-
|
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
|
725
289
|
|
726
|
-
|
727
|
-
|
728
|
-
$ docker info
|
729
|
-
$ docker system df # Check disk usage
|
730
|
-
$ docker system prune # Clean up unused resources
|
731
|
-
----
|
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/
|
732
292
|
|
733
|
-
|
293
|
+
# 5. Build the site from the resultset
|
294
|
+
$ bundle exec serialbench resultset build-site results/sets/docker-comparison/
|
734
295
|
|
735
|
-
|
736
|
-
|
737
|
-
# Remove all Serialbench images
|
738
|
-
$ docker rmi $(docker images serialbench -q)
|
739
|
-
|
740
|
-
# Remove all containers
|
741
|
-
$ docker container prune
|
296
|
+
# 6. Open the generated site
|
297
|
+
$ open _site/index.html
|
742
298
|
----
|
743
299
|
|
744
|
-
===
|
300
|
+
=== ASDF-based testing
|
745
301
|
|
746
|
-
|
747
|
-
|
748
|
-
Edit the `RUBY_VERSIONS` array in `docker/run-benchmarks.sh`:
|
302
|
+
WARNING: THIS IS NOT YET WORKING.
|
749
303
|
|
750
304
|
[source,bash]
|
751
305
|
----
|
752
|
-
|
753
|
-
|
306
|
+
# 1. Validate configuration
|
307
|
+
$ bundle exec serialbench benchmark validate serialbench-asdf.yml
|
754
308
|
|
755
|
-
|
309
|
+
# 2. Prepare Ruby environments
|
310
|
+
$ bundle exec serialbench benchmark prepare asdf --config=serialbench-asdf.yml
|
756
311
|
|
757
|
-
|
312
|
+
# 3. Run benchmarks across all Ruby versions
|
313
|
+
$ bundle exec serialbench benchmark execute asdf --config=serialbench-asdf.yml
|
758
314
|
|
759
|
-
|
760
|
-
|
761
|
-
# config/custom.yml
|
762
|
-
formats:
|
763
|
-
- xml
|
764
|
-
- json
|
765
|
-
iterations: 50
|
766
|
-
warmup: 5
|
767
|
-
data_sizes:
|
768
|
-
- small
|
769
|
-
- medium
|
315
|
+
# 4. Results are automatically merged and dashboard generated
|
316
|
+
$ open asdf-results/_site/index.html
|
770
317
|
----
|
771
318
|
|
772
|
-
Reference the custom config in the run script:
|
773
319
|
|
774
|
-
[source,bash]
|
775
|
-
----
|
776
|
-
# In docker/run-benchmarks.sh
|
777
|
-
CONFIG_FILE="config/custom.yml"
|
778
|
-
----
|
779
|
-
|
780
|
-
==== Output directory customization
|
781
|
-
|
782
|
-
Change the output directory in the run script:
|
783
320
|
|
784
|
-
[source,bash]
|
785
|
-
----
|
786
|
-
# In docker/run-benchmarks.sh
|
787
|
-
OUTPUT_DIR="my-benchmark-results"
|
788
|
-
----
|
789
321
|
|
790
|
-
|
322
|
+
== Configuration Files
|
791
323
|
|
792
|
-
|
324
|
+
=== Environment configuration
|
793
325
|
|
794
|
-
|
326
|
+
Environment configuration files define how benchmarks are executed in different runtime environments.
|
795
327
|
|
328
|
+
.Environment configuration for Docker (`config/environments/docker-ruby-3.4.yml`)
|
796
329
|
[source,yaml]
|
797
330
|
----
|
798
|
-
|
799
|
-
name:
|
800
|
-
|
801
|
-
|
802
|
-
|
803
|
-
|
804
|
-
|
805
|
-
|
806
|
-
|
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
|
-
----
|
880
|
-
|
881
|
-
List all available serializers:
|
882
|
-
|
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
|
920
|
-
----
|
921
|
-
|
922
|
-
XML-only parsing performance:
|
923
|
-
|
924
|
-
[source]
|
925
|
-
----
|
926
|
-
$ serialbench benchmark --formats xml --parsing-only
|
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'
|
927
340
|
----
|
928
341
|
|
929
|
-
|
930
|
-
|
931
|
-
[source]
|
932
|
-
----
|
933
|
-
$ serialbench benchmark --formats xml --generation-only
|
934
|
-
----
|
935
|
-
|
936
|
-
XML streaming/SAX parsing:
|
937
|
-
|
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
|
-
|
952
|
-
Test specific JSON libraries:
|
953
|
-
|
954
|
-
[source]
|
955
|
-
----
|
956
|
-
$ serialbench benchmark --formats json --parsers oj,json
|
957
|
-
$ serialbench benchmark --formats json --parsers yajl,oj
|
958
|
-
----
|
959
|
-
|
960
|
-
===== TOML benchmarks
|
961
|
-
|
962
|
-
Run all TOML library benchmarks:
|
963
|
-
|
964
|
-
[source]
|
965
|
-
----
|
966
|
-
$ serialbench benchmark --formats toml
|
967
|
-
----
|
968
|
-
|
969
|
-
Test specific TOML libraries:
|
970
|
-
|
971
|
-
[source]
|
342
|
+
.Environment configuration for ASDF (`config/environments/asdf-ruby-3.3.yml`)
|
343
|
+
[source,yaml]
|
972
344
|
----
|
973
|
-
|
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
|
974
353
|
----
|
975
354
|
|
976
|
-
|
977
|
-
|
978
|
-
Compare XML vs JSON performance:
|
979
|
-
|
980
|
-
[source]
|
981
|
-
----
|
982
|
-
$ serialbench benchmark --formats xml json
|
983
|
-
----
|
355
|
+
=== Benchmark configuration
|
984
356
|
|
985
|
-
|
357
|
+
Benchmark configuration files control what tests to run and how to run them.
|
986
358
|
|
987
|
-
|
988
|
-
|
989
|
-
$ serialbench benchmark --formats xml json toml
|
359
|
+
.Short configuration (CI-friendly) (`config/benchmarks/short.yml`)
|
360
|
+
[source,yaml]
|
990
361
|
----
|
362
|
+
name: short-benchmark
|
991
363
|
|
992
|
-
|
993
|
-
|
994
|
-
Memory profiling across formats:
|
995
|
-
|
996
|
-
[source]
|
997
|
-
----
|
998
|
-
$ serialbench benchmark --memory-profiling
|
999
|
-
----
|
364
|
+
data_sizes:
|
365
|
+
- small
|
1000
366
|
|
1001
|
-
|
367
|
+
formats:
|
368
|
+
- xml
|
369
|
+
- json
|
370
|
+
- yaml
|
371
|
+
- toml
|
1002
372
|
|
1003
|
-
|
1004
|
-
|
1005
|
-
|
1006
|
-
|
373
|
+
iterations:
|
374
|
+
small: 5
|
375
|
+
medium: 2
|
376
|
+
large: 1
|
1007
377
|
|
1008
|
-
|
378
|
+
operations:
|
379
|
+
- parse
|
380
|
+
- generate
|
381
|
+
- streaming
|
1009
382
|
|
1010
|
-
|
1011
|
-
----
|
1012
|
-
$ serialbench benchmark --output-format json
|
383
|
+
warmup: 2
|
1013
384
|
----
|
1014
385
|
|
1015
|
-
|
1016
|
-
|
1017
|
-
[source]
|
1018
|
-
----
|
1019
|
-
$ serialbench benchmark --data-sizes small,medium --iterations 100
|
386
|
+
.Full configuration (Comprehensive) (`config/benchmarks/full.yml`)
|
387
|
+
[source,yaml]
|
1020
388
|
----
|
389
|
+
name: full-benchmark
|
1021
390
|
|
1022
|
-
|
391
|
+
data_sizes:
|
392
|
+
- small
|
393
|
+
- medium
|
394
|
+
- large
|
1023
395
|
|
1024
|
-
|
396
|
+
formats:
|
397
|
+
- xml
|
398
|
+
- json
|
399
|
+
- yaml
|
400
|
+
- toml
|
1025
401
|
|
1026
|
-
|
1027
|
-
|
1028
|
-
|
1029
|
-
|
402
|
+
iterations:
|
403
|
+
small: 20
|
404
|
+
medium: 5
|
405
|
+
large: 2
|
1030
406
|
|
1031
|
-
|
407
|
+
operations:
|
408
|
+
- parse
|
409
|
+
- generate
|
410
|
+
- streaming
|
411
|
+
- memory
|
1032
412
|
|
1033
|
-
|
1034
|
-
----
|
1035
|
-
$ serialbench github_pages ruby-3.0/results ruby-3.1/results ruby-3.2/results docs/
|
413
|
+
warmup: 3
|
1036
414
|
----
|
1037
415
|
|
1038
|
-
|
416
|
+
== Results structure
|
1039
417
|
|
1040
|
-
|
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
|
418
|
+
=== Individual run results
|
1044
419
|
|
1045
|
-
|
420
|
+
Results are stored in a structured directory format, with each run containing
|
421
|
+
raw benchmark data and execution logs.
|
1046
422
|
|
1047
|
-
|
423
|
+
The directory is located at `results/runs/{name}/`, where `{name}` is the name
|
424
|
+
of the environment used for the benchmark.
|
1048
425
|
|
1049
426
|
[source]
|
1050
427
|
----
|
1051
|
-
|
428
|
+
results/runs/docker-ruby-33-results/
|
429
|
+
├── results.yaml # Raw benchmark data
|
430
|
+
└── benchmark.log # Execution log
|
1052
431
|
----
|
1053
432
|
|
1054
|
-
|
433
|
+
=== ResultSet structure
|
1055
434
|
|
1056
|
-
|
1057
|
-
|
1058
|
-
|
1059
|
-
* **Handles both parsing and generation** benchmark results
|
1060
|
-
* **Provides summary statistics** about processed data
|
1061
|
-
|
1062
|
-
Generate platform comparison reports:
|
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.
|
1063
438
|
|
1064
439
|
[source]
|
1065
440
|
----
|
1066
|
-
|
1067
|
-
|
1068
|
-
|
1069
|
-
This creates a JSON report with:
|
1070
|
-
|
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
|
1078
|
-
|
1079
|
-
[source]
|
1080
|
-
----
|
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
|
441
|
+
results/sets/ruby-version-comparison/
|
442
|
+
└── resultset.yml # Result set configuration
|
1198
443
|
----
|
1199
444
|
|
1200
445
|
== Benchmark categories
|
@@ -1221,105 +466,32 @@ it, which processes data sequentially and is memory-efficient for large files.
|
|
1221
466
|
Profiles memory allocation and retention during serialization operations using
|
1222
467
|
the `memory_profiler` gem.
|
1223
468
|
|
469
|
+
== Interactive Dashboard Features
|
1224
470
|
|
1225
|
-
|
1226
|
-
|
1227
|
-
=== Generated files
|
471
|
+
The generated HTML sites provide comprehensive interactive dashboards with:
|
1228
472
|
|
1229
|
-
|
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
|
1230
478
|
|
1231
|
-
|
1232
|
-
|
1233
|
-
|
1234
|
-
|
1235
|
-
|
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
|
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
|
1289
484
|
|
1290
|
-
===
|
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
|
1291
490
|
|
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
|
1296
|
-
|
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
491
|
|
1320
492
|
== Development
|
1321
493
|
|
1322
|
-
=== Running
|
494
|
+
=== Running Tests
|
1323
495
|
|
1324
496
|
[source]
|
1325
497
|
----
|
@@ -1327,15 +499,7 @@ $ bundle exec rake
|
|
1327
499
|
$ bundle exec rspec
|
1328
500
|
----
|
1329
501
|
|
1330
|
-
===
|
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
|
502
|
+
=== Adding a new serializers
|
1339
503
|
|
1340
504
|
To add support for additional serialization libraries:
|
1341
505
|
|
@@ -1345,76 +509,50 @@ To add support for additional serialization libraries:
|
|
1345
509
|
. Add the serializer to the registry in `lib/serialbench/serializers.rb`
|
1346
510
|
. Update documentation and tests
|
1347
511
|
|
1348
|
-
|
512
|
+
=== Contributing
|
1349
513
|
|
1350
|
-
|
1351
|
-
|
1352
|
-
|
1353
|
-
|
1354
|
-
|
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
|
-
----
|
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
|
1378
519
|
|
1379
|
-
== Architecture
|
1380
520
|
|
1381
|
-
|
521
|
+
== Known issues
|
1382
522
|
|
1383
|
-
|
1384
|
-
----
|
1385
|
-
BaseSerializer
|
1386
|
-
├── BaseXmlSerializer
|
1387
|
-
│ └── RexmlSerializer
|
1388
|
-
├── BaseJsonSerializer
|
1389
|
-
│ ├── JsonSerializer
|
1390
|
-
│ └── OjSerializer
|
1391
|
-
└── BaseTomlSerializer
|
1392
|
-
└── TomlRbSerializer
|
1393
|
-
----
|
523
|
+
=== Syck YAML serializer segmentation faults
|
1394
524
|
|
1395
|
-
|
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:
|
1396
528
|
|
1397
|
-
*
|
1398
|
-
*
|
1399
|
-
*
|
1400
|
-
* **ReportGenerator**: Creates HTML/AsciiDoc reports
|
1401
|
-
* **ChartGenerator**: Creates performance visualizations
|
1402
|
-
* **MemoryProfiler**: Analyzes memory usage patterns
|
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)
|
1403
532
|
|
1404
|
-
|
533
|
+
=== Syck overrides YAML constant
|
1405
534
|
|
1406
|
-
|
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.
|
539
|
+
|
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:
|
542
|
+
|
543
|
+
[source,ruby]
|
544
|
+
----
|
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)
|
548
|
+
----
|
1407
549
|
|
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
550
|
|
1412
|
-
==
|
551
|
+
== License and copyright
|
1413
552
|
|
1414
|
-
|
1415
|
-
https://www.ribose.com[Ribose Inc.]
|
553
|
+
Copyright Ribose.
|
1416
554
|
|
1417
|
-
|
555
|
+
This gem is developed, maintained and funded by https://www.ribose.com[Ribose]
|
1418
556
|
|
1419
557
|
The gem is available as open source under the terms of the
|
1420
558
|
https://opensource.org/licenses/BSD-2-Clause[2-Clause BSD License].
|