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.
- checksums.yaml +4 -4
- data/.github/scripts/push-to-data.sh +65 -0
- data/.github/workflows/benchmark.yml +98 -172
- data/.github/workflows/release.yml +68 -13
- data/Gemfile +1 -1
- data/config/benchmarks/full-json.yml +25 -0
- data/config/benchmarks/full-toml.yml +25 -0
- data/config/benchmarks/full-xml.yml +26 -0
- data/config/benchmarks/full-yaml.yml +25 -0
- data/config/benchmarks/full.yml +9 -4
- data/lib/serialbench/benchmark_runner.rb +32 -320
- data/lib/serialbench/cli/benchmark_cli.rb +1 -1
- data/lib/serialbench/cli.rb +0 -12
- data/lib/serialbench/models/benchmark_result.rb +2 -0
- data/lib/serialbench/models/result_store.rb +0 -38
- data/lib/serialbench/models.rb +0 -5
- data/lib/serialbench/serializers/base_serializer.rb +11 -3
- data/lib/serialbench/serializers/json/base_json_serializer.rb +8 -20
- data/lib/serialbench/serializers/json/json_serializer.rb +0 -16
- data/lib/serialbench/serializers/json/oj_serializer.rb +2 -17
- data/lib/serialbench/serializers/json/yajl_serializer.rb +2 -2
- data/lib/serialbench/serializers/toml/base_toml_serializer.rb +8 -29
- data/lib/serialbench/serializers/toml/toml_rb_serializer.rb +0 -16
- data/lib/serialbench/serializers/toml/tomlib_serializer.rb +0 -4
- data/lib/serialbench/serializers/toml/tomlrb_serializer.rb +2 -18
- data/lib/serialbench/serializers/xml/base_xml_serializer.rb +10 -26
- data/lib/serialbench/serializers/xml/leptris_serializer.rb +13 -10
- data/lib/serialbench/serializers/xml/libxml_serializer.rb +4 -9
- data/lib/serialbench/serializers/xml/nokogiri_serializer.rb +4 -9
- data/lib/serialbench/serializers/xml/oga_serializer.rb +6 -4
- data/lib/serialbench/serializers/xml/ox_serializer.rb +2 -2
- data/lib/serialbench/serializers/xml/rexml_serializer.rb +5 -12
- data/lib/serialbench/serializers/yaml/base_yaml_serializer.rb +1 -9
- data/lib/serialbench/serializers/yaml/syck_serializer.rb +0 -8
- data/lib/serialbench/test_data.rb +315 -0
- data/lib/serialbench/version.rb +1 -1
- data/lib/serialbench.rb +2 -1
- data/serialbench.gemspec +1 -2
- metadata +13 -59
- data/lib/serialbench/cli/resultset_cli.rb +0 -301
- data/lib/serialbench/models/result_set.rb +0 -79
- data/lib/serialbench/site_generator.rb +0 -337
- data/lib/serialbench/templates/assets/css/benchmark_report.css +0 -535
- data/lib/serialbench/templates/assets/css/format_based.css +0 -474
- data/lib/serialbench/templates/assets/css/themes.css +0 -589
- data/lib/serialbench/templates/assets/js/chart_helpers.js +0 -411
- data/lib/serialbench/templates/assets/js/dashboard.js +0 -795
- data/lib/serialbench/templates/assets/js/navigation.js +0 -142
- data/lib/serialbench/templates/base.liquid +0 -49
- data/lib/serialbench/templates/format_based.liquid +0 -507
- data/lib/serialbench/templates/partials/chart_section.liquid +0 -4
- data/site/.gitignore +0 -5
- data/site/README.md +0 -32
- data/site/astro.config.mjs +0 -12
- data/site/package-lock.json +0 -6160
- data/site/package.json +0 -22
- data/site/public/favicon.svg +0 -4
- data/site/scripts/gen-sample-data.mjs +0 -154
- data/site/src/components/AvailabilityMatrix.astro +0 -61
- data/site/src/components/CalibratedLeaderboard.vue +0 -134
- data/site/src/components/CitationBox.vue +0 -50
- data/site/src/components/DashboardConsole.vue +0 -193
- data/site/src/components/FeaturesTable.astro +0 -97
- data/site/src/components/MemoryPanel.vue +0 -44
- data/site/src/components/OpsChart.vue +0 -135
- data/site/src/config.ts +0 -18
- data/site/src/layouts/Layout.astro +0 -85
- data/site/src/lib/channels.ts +0 -24
- data/site/src/lib/dashboard.ts +0 -269
- data/site/src/pages/index.astro +0 -44
- data/site/src/pages/library/[slug].astro +0 -128
- data/site/src/pages/methodology.astro +0 -55
- data/site/src/styles/global.css +0 -103
- 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/
|
|
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.
|
|
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:
|
|
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/
|
|
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
|
-
|
|
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/
|
|
390
|
-
source_code_uri: https://github.com/
|
|
391
|
-
bug_tracker_uri: https://github.com/
|
|
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.
|
|
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
|