serialbench 0.2.0 → 0.4.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (74) hide show
  1. checksums.yaml +4 -4
  2. data/.github/scripts/push-to-data.sh +65 -0
  3. data/.github/workflows/benchmark.yml +98 -172
  4. data/.github/workflows/release.yml +68 -13
  5. data/Gemfile +1 -1
  6. data/config/benchmarks/full-json.yml +25 -0
  7. data/config/benchmarks/full-toml.yml +25 -0
  8. data/config/benchmarks/full-xml.yml +26 -0
  9. data/config/benchmarks/full-yaml.yml +25 -0
  10. data/config/benchmarks/full.yml +9 -4
  11. data/lib/serialbench/benchmark_runner.rb +32 -320
  12. data/lib/serialbench/cli/benchmark_cli.rb +1 -1
  13. data/lib/serialbench/cli.rb +0 -12
  14. data/lib/serialbench/models/benchmark_result.rb +2 -0
  15. data/lib/serialbench/models/result_store.rb +0 -38
  16. data/lib/serialbench/models.rb +0 -5
  17. data/lib/serialbench/serializers/base_serializer.rb +11 -3
  18. data/lib/serialbench/serializers/json/base_json_serializer.rb +8 -20
  19. data/lib/serialbench/serializers/json/json_serializer.rb +0 -16
  20. data/lib/serialbench/serializers/json/oj_serializer.rb +2 -17
  21. data/lib/serialbench/serializers/json/yajl_serializer.rb +2 -2
  22. data/lib/serialbench/serializers/toml/base_toml_serializer.rb +8 -29
  23. data/lib/serialbench/serializers/toml/toml_rb_serializer.rb +0 -16
  24. data/lib/serialbench/serializers/toml/tomlib_serializer.rb +0 -4
  25. data/lib/serialbench/serializers/toml/tomlrb_serializer.rb +2 -18
  26. data/lib/serialbench/serializers/xml/base_xml_serializer.rb +10 -26
  27. data/lib/serialbench/serializers/xml/leptris_serializer.rb +13 -10
  28. data/lib/serialbench/serializers/xml/libxml_serializer.rb +4 -9
  29. data/lib/serialbench/serializers/xml/nokogiri_serializer.rb +4 -9
  30. data/lib/serialbench/serializers/xml/oga_serializer.rb +6 -4
  31. data/lib/serialbench/serializers/xml/ox_serializer.rb +2 -2
  32. data/lib/serialbench/serializers/xml/rexml_serializer.rb +5 -12
  33. data/lib/serialbench/serializers/yaml/base_yaml_serializer.rb +1 -9
  34. data/lib/serialbench/serializers/yaml/syck_serializer.rb +0 -8
  35. data/lib/serialbench/test_data.rb +315 -0
  36. data/lib/serialbench/version.rb +1 -1
  37. data/lib/serialbench.rb +2 -1
  38. data/serialbench.gemspec +1 -2
  39. metadata +13 -59
  40. data/lib/serialbench/cli/resultset_cli.rb +0 -301
  41. data/lib/serialbench/models/result_set.rb +0 -79
  42. data/lib/serialbench/site_generator.rb +0 -337
  43. data/lib/serialbench/templates/assets/css/benchmark_report.css +0 -535
  44. data/lib/serialbench/templates/assets/css/format_based.css +0 -474
  45. data/lib/serialbench/templates/assets/css/themes.css +0 -589
  46. data/lib/serialbench/templates/assets/js/chart_helpers.js +0 -411
  47. data/lib/serialbench/templates/assets/js/dashboard.js +0 -795
  48. data/lib/serialbench/templates/assets/js/navigation.js +0 -142
  49. data/lib/serialbench/templates/base.liquid +0 -49
  50. data/lib/serialbench/templates/format_based.liquid +0 -507
  51. data/lib/serialbench/templates/partials/chart_section.liquid +0 -4
  52. data/site/.gitignore +0 -5
  53. data/site/README.md +0 -32
  54. data/site/astro.config.mjs +0 -12
  55. data/site/package-lock.json +0 -6160
  56. data/site/package.json +0 -22
  57. data/site/public/favicon.svg +0 -4
  58. data/site/scripts/gen-sample-data.mjs +0 -154
  59. data/site/src/components/AvailabilityMatrix.astro +0 -61
  60. data/site/src/components/CalibratedLeaderboard.vue +0 -134
  61. data/site/src/components/CitationBox.vue +0 -50
  62. data/site/src/components/DashboardConsole.vue +0 -193
  63. data/site/src/components/FeaturesTable.astro +0 -97
  64. data/site/src/components/MemoryPanel.vue +0 -44
  65. data/site/src/components/OpsChart.vue +0 -135
  66. data/site/src/config.ts +0 -18
  67. data/site/src/layouts/Layout.astro +0 -85
  68. data/site/src/lib/channels.ts +0 -24
  69. data/site/src/lib/dashboard.ts +0 -269
  70. data/site/src/pages/index.astro +0 -44
  71. data/site/src/pages/library/[slug].astro +0 -128
  72. data/site/src/pages/methodology.astro +0 -55
  73. data/site/src/styles/global.css +0 -103
  74. data/site/tsconfig.json +0 -5
data/lib/serialbench.rb CHANGED
@@ -6,8 +6,9 @@ require_relative 'serialbench/benchmark_runner'
6
6
  require_relative 'serialbench/cli'
7
7
  require_relative 'serialbench/memory_profiler'
8
8
  require_relative 'serialbench/models'
9
- require_relative 'serialbench/site_generator'
10
9
 
11
10
  module Serialbench
11
+ autoload :TestData, 'serialbench/test_data'
12
+
12
13
  class Error < StandardError; end
13
14
  end
data/serialbench.gemspec CHANGED
@@ -14,7 +14,7 @@ Gem::Specification.new do |spec|
14
14
 
15
15
  spec.summary = 'Comprehensive serialization benchmarking tool for Ruby'
16
16
  spec.description = 'A benchmarking suite for comparing performance of various serialization libraries in Ruby, including XML, JSON, and TOML parsers/generators.'
17
- spec.homepage = 'https://github.com/metanorma/serialbench'
17
+ spec.homepage = 'https://github.com/serialbench/serialbench'
18
18
  spec.license = 'BSD-2-Clause'
19
19
  spec.required_ruby_version = Gem::Requirement.new('>= 2.7.0')
20
20
 
@@ -42,7 +42,6 @@ Gem::Specification.new do |spec|
42
42
 
43
43
  # Reporting dependencies
44
44
  spec.add_dependency 'csv' # Required from Ruby 3.4+
45
- spec.add_dependency 'liquid' # Template engine for HTML reports
46
45
 
47
46
  # XML serializers
48
47
  spec.add_dependency 'oga'
metadata CHANGED
@@ -1,14 +1,13 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: serialbench
3
3
  version: !ruby/object:Gem::Version
4
- version: 0.2.0
4
+ version: 0.4.0
5
5
  platform: ruby
6
6
  authors:
7
7
  - Ribose
8
- autorequire:
9
8
  bindir: exe
10
9
  cert_chain: []
11
- date: 2026-08-24 00:00:00.000000000 Z
10
+ date: 1980-01-02 00:00:00.000000000 Z
12
11
  dependencies:
13
12
  - !ruby/object:Gem::Dependency
14
13
  name: benchmark-ips
@@ -94,20 +93,6 @@ dependencies:
94
93
  - - ">="
95
94
  - !ruby/object:Gem::Version
96
95
  version: '0'
97
- - !ruby/object:Gem::Dependency
98
- name: liquid
99
- requirement: !ruby/object:Gem::Requirement
100
- requirements:
101
- - - ">="
102
- - !ruby/object:Gem::Version
103
- version: '0'
104
- type: :runtime
105
- prerelease: false
106
- version_requirements: !ruby/object:Gem::Requirement
107
- requirements:
108
- - - ">="
109
- - !ruby/object:Gem::Version
110
- version: '0'
111
96
  - !ruby/object:Gem::Dependency
112
97
  name: oga
113
98
  requirement: !ruby/object:Gem::Requirement
@@ -271,6 +256,7 @@ executables:
271
256
  extensions: []
272
257
  extra_rdoc_files: []
273
258
  files:
259
+ - ".github/scripts/push-to-data.sh"
274
260
  - ".github/workflows/benchmark.yml"
275
261
  - ".github/workflows/rake.yml"
276
262
  - ".github/workflows/release.yml"
@@ -282,6 +268,10 @@ files:
282
268
  - Gemfile
283
269
  - README.adoc
284
270
  - Rakefile
271
+ - config/benchmarks/full-json.yml
272
+ - config/benchmarks/full-toml.yml
273
+ - config/benchmarks/full-xml.yml
274
+ - config/benchmarks/full-yaml.yml
285
275
  - config/benchmarks/full.yml
286
276
  - config/benchmarks/short.yml
287
277
  - config/environments/asdf-ruby-3.2.yml
@@ -307,7 +297,6 @@ files:
307
297
  - lib/serialbench/cli/base_cli.rb
308
298
  - lib/serialbench/cli/benchmark_cli.rb
309
299
  - lib/serialbench/cli/environment_cli.rb
310
- - lib/serialbench/cli/resultset_cli.rb
311
300
  - lib/serialbench/cli/ruby_build_cli.rb
312
301
  - lib/serialbench/cli/validate_cli.rb
313
302
  - lib/serialbench/config_manager.rb
@@ -318,7 +307,6 @@ files:
318
307
  - lib/serialbench/models/environment_config.rb
319
308
  - lib/serialbench/models/platform.rb
320
309
  - lib/serialbench/models/result.rb
321
- - lib/serialbench/models/result_set.rb
322
310
  - lib/serialbench/models/result_store.rb
323
311
  - lib/serialbench/ruby_build_manager.rb
324
312
  - lib/serialbench/runners/asdf_runner.rb
@@ -346,50 +334,17 @@ files:
346
334
  - lib/serialbench/serializers/yaml/base_yaml_serializer.rb
347
335
  - lib/serialbench/serializers/yaml/psych_serializer.rb
348
336
  - lib/serialbench/serializers/yaml/syck_serializer.rb
349
- - lib/serialbench/site_generator.rb
350
- - lib/serialbench/templates/assets/css/benchmark_report.css
351
- - lib/serialbench/templates/assets/css/format_based.css
352
- - lib/serialbench/templates/assets/css/themes.css
353
- - lib/serialbench/templates/assets/js/chart_helpers.js
354
- - lib/serialbench/templates/assets/js/dashboard.js
355
- - lib/serialbench/templates/assets/js/navigation.js
356
- - lib/serialbench/templates/base.liquid
357
- - lib/serialbench/templates/format_based.liquid
358
- - lib/serialbench/templates/partials/chart_section.liquid
337
+ - lib/serialbench/test_data.rb
359
338
  - lib/serialbench/version.rb
360
339
  - lib/serialbench/yaml_validator.rb
361
340
  - serialbench.gemspec
362
- - site/.gitignore
363
- - site/README.md
364
- - site/astro.config.mjs
365
- - site/package-lock.json
366
- - site/package.json
367
- - site/public/favicon.svg
368
- - site/scripts/gen-sample-data.mjs
369
- - site/src/components/AvailabilityMatrix.astro
370
- - site/src/components/CalibratedLeaderboard.vue
371
- - site/src/components/CitationBox.vue
372
- - site/src/components/DashboardConsole.vue
373
- - site/src/components/FeaturesTable.astro
374
- - site/src/components/MemoryPanel.vue
375
- - site/src/components/OpsChart.vue
376
- - site/src/config.ts
377
- - site/src/layouts/Layout.astro
378
- - site/src/lib/channels.ts
379
- - site/src/lib/dashboard.ts
380
- - site/src/pages/index.astro
381
- - site/src/pages/library/[slug].astro
382
- - site/src/pages/methodology.astro
383
- - site/src/styles/global.css
384
- - site/tsconfig.json
385
- homepage: https://github.com/metanorma/serialbench
341
+ homepage: https://github.com/serialbench/serialbench
386
342
  licenses:
387
343
  - BSD-2-Clause
388
344
  metadata:
389
- homepage_uri: https://github.com/metanorma/serialbench
390
- source_code_uri: https://github.com/metanorma/serialbench
391
- bug_tracker_uri: https://github.com/metanorma/serialbench/issues
392
- post_install_message:
345
+ homepage_uri: https://github.com/serialbench/serialbench
346
+ source_code_uri: https://github.com/serialbench/serialbench
347
+ bug_tracker_uri: https://github.com/serialbench/serialbench/issues
393
348
  rdoc_options: []
394
349
  require_paths:
395
350
  - lib
@@ -404,8 +359,7 @@ required_rubygems_version: !ruby/object:Gem::Requirement
404
359
  - !ruby/object:Gem::Version
405
360
  version: '0'
406
361
  requirements: []
407
- rubygems_version: 3.5.22
408
- signing_key:
362
+ rubygems_version: 3.6.9
409
363
  specification_version: 4
410
364
  summary: Comprehensive serialization benchmarking tool for Ruby
411
365
  test_files: []
@@ -1,301 +0,0 @@
1
- # frozen_string_literal: true
2
-
3
- require_relative 'base_cli'
4
- require_relative '../models/result_set'
5
- require_relative '../site_generator'
6
-
7
- module Serialbench
8
- module Cli
9
- # CLI for managing benchmark resultsets (collections of runs)
10
- class ResultsetCli < BaseCli
11
- desc 'create NAME PATH', 'Create a new resultset'
12
- long_desc <<~DESC
13
- Create a new resultset (collection of benchmark runs).
14
-
15
- NAME is required and must be unique.
16
- PATH is the directory where the resultset will be created.
17
-
18
- Examples:
19
- serialbench resultset create performance-comparison results/sets/performance-comparison
20
- serialbench resultset create cross-platform-test results/sets/cross-platform-test
21
- DESC
22
- def create(resultset_name, resultset_path)
23
- Serialbench::Models::ResultStore.default
24
-
25
- # Check if resultset already exists
26
- definition_path = File.join(resultset_path, 'resultset.yaml')
27
-
28
- if File.exist?(definition_path)
29
- say "ResultSet at '#{resultset_path}' already exists", :yellow
30
- return unless yes?('Create anyway with timestamp suffix? (y/n)')
31
-
32
- resultset_path = "#{resultset_path}-#{generate_timestamp}"
33
- end
34
-
35
- # Create empty resultset using the new ResultSet model
36
- resultset = Serialbench::Models::ResultSet.new(
37
- name: resultset_name,
38
- description: "ResultSet for #{resultset_name} benchmarks",
39
- created_at: Time.now.utc.iso8601,
40
- updated_at: Time.now.utc.iso8601
41
- )
42
- resultset.save(resultset_path)
43
-
44
- say "✅ Created resultset: #{resultset_path}", :green
45
- say "Path: #{definition_path}", :cyan
46
- say "Use 'serialbench resultset add-result' to add benchmark runs", :white
47
- rescue StandardError => e
48
- say "Error creating resultset: #{e.message}", :red
49
- exit 1
50
- end
51
-
52
- desc 'add-result RESULTSET_PATH RESULT_PATH...', 'Add one or more runs to a resultset'
53
- long_desc <<~DESC
54
- Add one or more benchmark runs to a resultset.
55
-
56
- RESULTSET_PATH is the path to the resultset directory
57
- RESULT_PATH... accepts multiple result paths (supports shell expansion)
58
-
59
- Examples:
60
- # Add single result
61
- serialbench resultset add-result results/sets/weekly results/runs/my-run
62
-
63
- # Add multiple results explicitly
64
- serialbench resultset add-result results/sets/weekly results/runs/run1 results/runs/run2
65
-
66
- # Add multiple results with shell expansion
67
- serialbench resultset add-result results/sets/weekly artifacts/benchmark-results-*/
68
- serialbench resultset add-result results/sets/weekly results/runs/*
69
- DESC
70
- def add_result(resultset_path, *result_paths)
71
- if result_paths.empty?
72
- say '❌ Error: At least one result path must be provided', :red
73
- exit 1
74
- end
75
-
76
- resultset = Serialbench::Models::ResultSet.load(resultset_path)
77
-
78
- say "📦 Adding #{result_paths.size} result(s) to resultset", :cyan
79
- say "ResultSet: #{resultset_path}", :white
80
- say ''
81
-
82
- added_count = 0
83
- failed_count = 0
84
- skipped_count = 0
85
-
86
- result_paths.each_with_index do |result_path, index|
87
- say "#{index + 1}/#{result_paths.size} Processing: #{result_path}", :cyan
88
-
89
- # Find results.yaml in the path or subdirectories
90
- results_file = if File.exist?(File.join(result_path, 'results.yaml'))
91
- File.join(result_path, 'results.yaml')
92
- else
93
- Dir.glob(File.join(result_path, '**/results.yaml')).first
94
- end
95
-
96
- unless results_file
97
- say ' ⚠️ No results.yaml found - skipping', :yellow
98
- skipped_count += 1
99
- next
100
- end
101
-
102
- result_dir = File.dirname(results_file)
103
-
104
- begin
105
- resultset.add_result(result_dir)
106
- say ' ✅ Added successfully', :green
107
- added_count += 1
108
- rescue StandardError => e
109
- say " ❌ Failed: #{e.message}", :red
110
- failed_count += 1
111
- end
112
- say ''
113
- end
114
-
115
- resultset.save(resultset_path)
116
-
117
- say '=' * 60, :cyan
118
- say 'Summary:', :green
119
- say " Total processed: #{result_paths.size}", :white
120
- say " ✅ Successfully added: #{added_count}", :green
121
- say " ❌ Failed: #{failed_count}", :red if failed_count > 0
122
- say " ⚠️ Skipped: #{skipped_count}", :yellow if skipped_count > 0
123
- say " 📊 Total results in set: #{resultset.results.count}", :cyan
124
- say '=' * 60, :cyan
125
-
126
- exit 1 if failed_count > 0 && added_count == 0
127
- rescue StandardError => e
128
- say "❌ Error: #{e.message}", :red
129
- exit 1
130
- end
131
-
132
- desc 'remove-result RESULTSET_PATH RESULT_PATH', 'Remove a run from a resultset'
133
- long_desc <<~DESC
134
- Remove a benchmark run from a resultset.
135
-
136
- RESULTSET_PATH must be specified explicitly
137
- RESULT_PATH is the path to the run result directory
138
-
139
- Examples:
140
- serialbench resultset remove-result results/sets/performance-comparison results/runs/my-run-local-macos-arm64-ruby-3.3.8
141
- serialbench resultset remove-result results/sets/cross-platform-test results/runs/my-docker-run
142
- DESC
143
- def remove_result(resultset_path, _result_path)
144
- Serialbench::Models::ResultStore.default
145
-
146
- # Find the resultset
147
- resultset = Serialbench::Models::ResultSet.load(resultset_path)
148
- if resultset.nil?
149
- say "ResultSet '#{resultset_path}' not found", :red
150
- exit 1
151
- end
152
-
153
- # Remove run from resultset
154
- removed = resultset.remove_run(run_identifier)
155
- unless removed
156
- say "Run '#{run_identifier}' not found in resultset", :yellow
157
- say 'Available runs in resultset:', :white
158
- resultset.runs.each do |run_info|
159
- say " - #{run_info[:name]}", :white
160
- end
161
- return
162
- end
163
-
164
- resultset.save
165
-
166
- say '✅ Removed run from resultset', :green
167
- say "Run: #{run_identifier}", :cyan
168
- say "ResultSet: #{resultset_path}", :cyan
169
- say "Remaining runs in set: #{resultset.runs.length}", :white
170
- rescue StandardError => e
171
- say "Error removing run from resultset: #{e.message}", :red
172
- exit 1
173
- end
174
-
175
- desc 'build-site RESULTSET_PATH [OUTPUT_DIR]', 'Generate HTML site for a resultset'
176
- long_desc <<~DESC
177
- Generate an HTML site for a resultset (comparative analysis).
178
-
179
- RESULTSET_PATH must be specified explicitly
180
- OUTPUT_DIR defaults to _site/
181
-
182
- Examples:
183
- serialbench resultset build-site results/sets/performance-comparison
184
- serialbench resultset build-site results/sets/cross-platform-test output/
185
- DESC
186
- def build_site(resultset_path, output_dir = '_site')
187
- unless Dir.exist?(resultset_path)
188
- say "ResultSet directory not found: #{resultset_path}", :red
189
- say "Please create a resultset first using 'serialbench resultset create'", :white
190
- exit 1
191
- end
192
-
193
- resultset = Serialbench::Models::ResultSet.load(resultset_path)
194
-
195
- if resultset.results.empty?
196
- say "ResultSet '#{resultset_path}' contains no runs", :yellow
197
- say "Use 'serialbench resultset add-result' to add runs first", :white
198
- return
199
- end
200
-
201
- say "🏗️ Generating HTML site for resultset: #{resultset_path}", :green
202
- say "Runs in set: #{resultset.results.size}", :cyan
203
-
204
- # Use the unified site generator for resultsets
205
- Serialbench::SiteGenerator.generate_for_resultset(resultset, output_dir)
206
-
207
- say '✅ HTML site generated successfully!', :green
208
- say "Site location: #{output_dir}", :cyan
209
- say "Open: #{File.join(output_dir, 'index.html')}", :white
210
- rescue StandardError => e
211
- say "Error generating site: #{e.message}", :red
212
- say "Details: #{e.backtrace.first(3).join("\n")}", :red if options[:verbose]
213
- exit 1
214
- end
215
-
216
- desc 'export-data RESULTSET_PATH OUTPUT_JSON', 'Export a resultset as the site dashboard JSON payload'
217
- long_desc <<~DESC
218
- Write the aggregated dashboard payload (combined_results, environments,
219
- metadata) for a resultset as JSON. This is the data contract consumed
220
- by the Astro site in site/.
221
-
222
- Optionally also export the raw per-environment YAML files and the
223
- complete resultset YAML for download links.
224
-
225
- Examples:
226
- serialbench resultset export-data results/sets/weekly site/src/data/sample.json --raw-data-dir site/public/data
227
- DESC
228
- method_option 'raw-data-dir', type: :string,
229
- desc: 'Also write per-environment YAML and resultset.yaml to this directory'
230
- def export_data(resultset_path, output_json)
231
- resultset = Serialbench::Models::ResultSet.load(resultset_path)
232
-
233
- if resultset.results.empty?
234
- say "ResultSet '#{resultset_path}' contains no runs", :yellow
235
- say "Use 'serialbench resultset add-result' to add runs first", :white
236
- exit 1
237
- end
238
-
239
- payload = Serialbench::SiteGenerator.resultset_payload(resultset)
240
- output_dir = File.dirname(File.expand_path(output_json))
241
- FileUtils.mkdir_p(output_dir)
242
- File.write(output_json, JSON.pretty_generate(payload))
243
-
244
- say "✅ Dashboard payload exported: #{output_json}", :green
245
- say "Environments: #{payload['environments'].size}", :cyan
246
-
247
- if options['raw-data-dir']
248
- Serialbench::SiteGenerator.export_raw_data(resultset, options['raw-data-dir'])
249
- say "📦 Raw YAML exported to: #{options['raw-data-dir']}", :cyan
250
- end
251
- rescue StandardError => e
252
- say "Error exporting data: #{e.message}", :red
253
- exit 1
254
- end
255
-
256
- desc 'list', 'List all available resultsets'
257
- long_desc <<~DESC
258
- List all resultsets in the results/sets/ directory.
259
-
260
- Shows resultset names, number of runs, and timestamps.
261
- DESC
262
- def list
263
- ensure_results_directory
264
-
265
- begin
266
- store = Serialbench::Models::ResultStore.default
267
- resultsets = store.find_resultsets
268
-
269
- if resultsets.empty?
270
- say 'No resultsets found', :yellow
271
- say "Use 'serialbench resultset create' to create a resultset", :white
272
- return
273
- end
274
-
275
- say 'Available ResultSets:', :green
276
- say '=' * 50, :green
277
-
278
- resultsets.each do |resultset|
279
- say "📁 #{resultset.name}", :cyan
280
- say " Runs: #{resultset.runs.length}", :white
281
- say " Created: #{resultset.metadata[:timestamp]}", :white
282
- say " Path: #{resultset.directory}", :white
283
-
284
- if resultset.runs.any?
285
- say ' Contains:', :white
286
- resultset.runs.first(3).each do |run_info|
287
- say " - #{run_info[:name]}", :white
288
- end
289
- say " ... and #{resultset.runs.length - 3} more" if resultset.runs.length > 3
290
- end
291
-
292
- say ''
293
- end
294
- rescue StandardError => e
295
- say "Error listing resultsets: #{e.message}", :red
296
- exit 1
297
- end
298
- end
299
- end
300
- end
301
- end
@@ -1,79 +0,0 @@
1
- # frozen_string_literal: true
2
-
3
- require 'yaml'
4
- require 'time'
5
- require 'fileutils'
6
-
7
- module Serialbench
8
- module Models
9
- # ResultSet model for managing collections of benchmark results
10
- class ResultSet < Lutaml::Model::Serializable
11
- attribute :name, :string
12
- attribute :description, :string
13
- attribute :created_at, :string, default: -> { Time.now.utc.iso8601 }
14
- attribute :updated_at, :string, default: -> { Time.now.utc.iso8601 }
15
- attribute :results, Result, collection: true, initialize_empty: true
16
-
17
- def self.load(path)
18
- raise ArgumentError, "Path does not exist: #{path}" unless Dir.exist?(path)
19
-
20
- # Load benchmark data
21
- data_file = File.join(path, 'resultset.yaml')
22
-
23
- raise ArgumentError, "No results data found in #{path}" unless File.exist?(data_file)
24
-
25
- from_yaml(IO.read(data_file))
26
- end
27
-
28
- def to_file(path)
29
- File.write(path, to_yaml)
30
- end
31
-
32
- def save(dir)
33
- FileUtils.mkdir_p(dir)
34
- to_file(File.join(dir, 'resultset.yaml'))
35
- end
36
-
37
- def add_result(result_path)
38
- # Assume result_path is the directory containing benchmark results and is named
39
- # accordingly
40
- result_name = File.basename(result_path)
41
- raise ArgumentError, 'Result name cannot be empty' if result_name.empty?
42
- # Validate that the result path is a directory
43
- raise ArgumentError, 'Result path must be a directory' unless File.directory?(result_path)
44
-
45
- result_file_path = File.join(result_path, 'results.yaml')
46
- raise ArgumentError, "No results data found in #{result_path}" unless File.exist?(result_file_path)
47
-
48
- result = Result.load(result_path)
49
-
50
- # Validate that the result has required fields
51
- raise ArgumentError, "Result from #{result_path} is missing platform information" if result.platform.nil?
52
- raise ArgumentError, "Result from #{result_path} is missing environment_config" if result.environment_config.nil?
53
- raise ArgumentError, "Result from #{result_path} is missing benchmark_config" if result.benchmark_config.nil?
54
-
55
- # Check if result already exists:
56
- # If environment_config.created_at is identical;
57
- # If platform.platform_string is identical;
58
- # If benchmark_config.benchmark_name is identical;
59
-
60
- duplicates = results.select do |r|
61
- # Skip results with nil platform (defensive check)
62
- next if r.platform.nil? || result.platform.nil?
63
-
64
- r.platform.platform_string == result.platform.platform_string &&
65
- r.environment_config.created_at == result.environment_config.created_at &&
66
- r.benchmark_config.benchmark_name == result.benchmark_config.benchmark_name
67
- end
68
-
69
- raise ArgumentError, 'Result is already present in this resultset' if duplicates.any?
70
-
71
- # Add the result to the resultset
72
- results << result
73
- self.updated_at = Time.now.utc.iso8601
74
-
75
- result
76
- end
77
- end
78
- end
79
- end