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
@@ -0,0 +1,142 @@
|
|
1
|
+
// Navigation and UI interaction functions for Serialbench reports
|
2
|
+
|
3
|
+
/**
|
4
|
+
* Show a specific section and update navigation state
|
5
|
+
*/
|
6
|
+
function showSection(sectionName) {
|
7
|
+
// Hide all sections
|
8
|
+
document.querySelectorAll('.section').forEach(section => {
|
9
|
+
section.classList.remove('active');
|
10
|
+
});
|
11
|
+
|
12
|
+
// Remove active class from all nav buttons
|
13
|
+
document.querySelectorAll('.nav-btn').forEach(btn => {
|
14
|
+
btn.classList.remove('active');
|
15
|
+
});
|
16
|
+
|
17
|
+
// Show selected section
|
18
|
+
const targetSection = document.getElementById(sectionName);
|
19
|
+
if (targetSection) {
|
20
|
+
targetSection.classList.add('active');
|
21
|
+
}
|
22
|
+
|
23
|
+
// Add active class to clicked button
|
24
|
+
if (event && event.target) {
|
25
|
+
event.target.classList.add('active');
|
26
|
+
}
|
27
|
+
|
28
|
+
// Smooth scroll to top of section
|
29
|
+
if (targetSection) {
|
30
|
+
targetSection.scrollIntoView({ behavior: 'smooth', block: 'start' });
|
31
|
+
}
|
32
|
+
}
|
33
|
+
|
34
|
+
/**
|
35
|
+
* Initialize navigation event listeners
|
36
|
+
*/
|
37
|
+
function initializeNavigation() {
|
38
|
+
// Add click event listeners to navigation buttons
|
39
|
+
document.querySelectorAll('.nav-btn').forEach(btn => {
|
40
|
+
btn.addEventListener('click', function(e) {
|
41
|
+
e.preventDefault();
|
42
|
+
const sectionName = this.getAttribute('data-section') ||
|
43
|
+
this.textContent.toLowerCase().replace(/\s+/g, '').replace('performance', '');
|
44
|
+
showSection(sectionName);
|
45
|
+
});
|
46
|
+
});
|
47
|
+
|
48
|
+
// Add keyboard navigation support
|
49
|
+
document.addEventListener('keydown', function(e) {
|
50
|
+
if (e.altKey) {
|
51
|
+
const keyMap = {
|
52
|
+
'1': 'parsing',
|
53
|
+
'2': 'generation',
|
54
|
+
'3': 'streaming',
|
55
|
+
'4': 'memory',
|
56
|
+
'5': 'summary',
|
57
|
+
'6': 'environments'
|
58
|
+
};
|
59
|
+
|
60
|
+
if (keyMap[e.key]) {
|
61
|
+
e.preventDefault();
|
62
|
+
showSection(keyMap[e.key]);
|
63
|
+
|
64
|
+
// Update button state
|
65
|
+
document.querySelectorAll('.nav-btn').forEach(btn => {
|
66
|
+
btn.classList.remove('active');
|
67
|
+
if (btn.textContent.toLowerCase().includes(keyMap[e.key]) ||
|
68
|
+
(keyMap[e.key] === 'parsing' && btn.textContent.toLowerCase().includes('parsing')) ||
|
69
|
+
(keyMap[e.key] === 'generation' && btn.textContent.toLowerCase().includes('generation')) ||
|
70
|
+
(keyMap[e.key] === 'streaming' && btn.textContent.toLowerCase().includes('streaming')) ||
|
71
|
+
(keyMap[e.key] === 'memory' && btn.textContent.toLowerCase().includes('memory')) ||
|
72
|
+
(keyMap[e.key] === 'summary' && btn.textContent.toLowerCase().includes('summary')) ||
|
73
|
+
(keyMap[e.key] === 'environments' && btn.textContent.toLowerCase().includes('environment'))) {
|
74
|
+
btn.classList.add('active');
|
75
|
+
}
|
76
|
+
});
|
77
|
+
}
|
78
|
+
}
|
79
|
+
});
|
80
|
+
}
|
81
|
+
|
82
|
+
/**
|
83
|
+
* Add loading states to charts
|
84
|
+
*/
|
85
|
+
function addChartLoadingStates() {
|
86
|
+
document.querySelectorAll('.chart-container canvas').forEach(canvas => {
|
87
|
+
const container = canvas.closest('.chart-container');
|
88
|
+
if (container) {
|
89
|
+
container.classList.add('loading');
|
90
|
+
|
91
|
+
// Remove loading state after chart is rendered
|
92
|
+
setTimeout(() => {
|
93
|
+
container.classList.remove('loading');
|
94
|
+
}, 1000);
|
95
|
+
}
|
96
|
+
});
|
97
|
+
}
|
98
|
+
|
99
|
+
/**
|
100
|
+
* Add tooltips to navigation buttons
|
101
|
+
*/
|
102
|
+
function addNavigationTooltips() {
|
103
|
+
const tooltips = {
|
104
|
+
'parsing': 'View parsing performance benchmarks (Alt+1)',
|
105
|
+
'generation': 'View generation performance benchmarks (Alt+2)',
|
106
|
+
'streaming': 'View streaming performance benchmarks (Alt+3)',
|
107
|
+
'memory': 'View memory usage analysis (Alt+4)',
|
108
|
+
'summary': 'View performance summary and recommendations (Alt+5)',
|
109
|
+
'environments': 'View environment and version details (Alt+6)'
|
110
|
+
};
|
111
|
+
|
112
|
+
document.querySelectorAll('.nav-btn').forEach(btn => {
|
113
|
+
const text = btn.textContent.toLowerCase();
|
114
|
+
for (const [key, tooltip] of Object.entries(tooltips)) {
|
115
|
+
if (text.includes(key) || (key === 'environments' && text.includes('environment'))) {
|
116
|
+
btn.title = tooltip;
|
117
|
+
break;
|
118
|
+
}
|
119
|
+
}
|
120
|
+
});
|
121
|
+
}
|
122
|
+
|
123
|
+
/**
|
124
|
+
* Initialize all UI enhancements
|
125
|
+
*/
|
126
|
+
function initializeUI() {
|
127
|
+
// Wait for DOM to be fully loaded
|
128
|
+
if (document.readyState === 'loading') {
|
129
|
+
document.addEventListener('DOMContentLoaded', function() {
|
130
|
+
initializeNavigation();
|
131
|
+
addNavigationTooltips();
|
132
|
+
addChartLoadingStates();
|
133
|
+
});
|
134
|
+
} else {
|
135
|
+
initializeNavigation();
|
136
|
+
addNavigationTooltips();
|
137
|
+
addChartLoadingStates();
|
138
|
+
}
|
139
|
+
}
|
140
|
+
|
141
|
+
// Auto-initialize when script loads
|
142
|
+
initializeUI();
|
@@ -0,0 +1,49 @@
|
|
1
|
+
<!DOCTYPE html>
|
2
|
+
<html lang="en">
|
3
|
+
<head>
|
4
|
+
<meta charset="UTF-8">
|
5
|
+
<meta name="viewport" content="width=device-width, initial-scale=1.0">
|
6
|
+
<title>{{ page_title | default: "Serialbench Results" }}</title>
|
7
|
+
|
8
|
+
<!-- Preload fonts -->
|
9
|
+
<link rel="preconnect" href="https://fonts.googleapis.com">
|
10
|
+
<link rel="preconnect" href="https://fonts.gstatic.com" crossorigin>
|
11
|
+
<link href="https://fonts.googleapis.com/css2?family=Inter:wght@400;500;600;700&display=swap" rel="stylesheet">
|
12
|
+
|
13
|
+
<!-- Chart.js -->
|
14
|
+
<script src="https://cdn.jsdelivr.net/npm/chart.js@4.4.0/dist/chart.umd.js" defer></script>
|
15
|
+
|
16
|
+
<!-- CSS -->
|
17
|
+
<link rel="stylesheet" href="assets/css/benchmark_report.css">
|
18
|
+
|
19
|
+
<!-- Favicon -->
|
20
|
+
<link rel="icon" type="image/svg+xml" href="data:image/svg+xml,%3csvg xmlns='http://www.w3.org/2000/svg' fill='%23F97316' viewBox='0 0 24 24'%3e%3cpath d='M12 2L2 7v10c0 5.55 3.84 9.95 9 11 5.16-1.05 9-5.45 9-11V7l-10-5z'/%3e%3c/svg%3e">
|
21
|
+
</head>
|
22
|
+
<body>
|
23
|
+
<!-- Navigation Bar -->
|
24
|
+
<nav class="navbar">
|
25
|
+
<div class="navbar-container">
|
26
|
+
<div class="navbar-header">
|
27
|
+
<a href="#" class="navbar-brand">
|
28
|
+
<div class="navbar-brand-icon">
|
29
|
+
<svg width="20" height="20" fill="currentColor" viewBox="0 0 24 24">
|
30
|
+
<path d="M12 2L2 7v10c0 5.55 3.84 9.95 9 11 5.16-1.05 9-5.45 9-11V7l-10-5z"/>
|
31
|
+
</svg>
|
32
|
+
</div>
|
33
|
+
Serialbench
|
34
|
+
</a>
|
35
|
+
</div>
|
36
|
+
</div>
|
37
|
+
</nav>
|
38
|
+
|
39
|
+
<!-- Main Content -->
|
40
|
+
<main class="main-content">
|
41
|
+
{{ content }}
|
42
|
+
</main>
|
43
|
+
|
44
|
+
<!-- JavaScript -->
|
45
|
+
<script src="assets/js/chart_helpers.js" defer></script>
|
46
|
+
<script src="assets/js/navigation.js" defer></script>
|
47
|
+
|
48
|
+
</body>
|
49
|
+
</html>
|
@@ -0,0 +1,279 @@
|
|
1
|
+
<!DOCTYPE html>
|
2
|
+
<html lang="en">
|
3
|
+
<head>
|
4
|
+
<meta charset="UTF-8">
|
5
|
+
<meta name="viewport" content="width=device-width, initial-scale=1.0">
|
6
|
+
<title>SerialBench - Format Performance Dashboard</title>
|
7
|
+
|
8
|
+
<!-- Preload fonts -->
|
9
|
+
<link rel="preconnect" href="https://fonts.googleapis.com">
|
10
|
+
<link rel="preconnect" href="https://fonts.gstatic.com" crossorigin>
|
11
|
+
<link href="https://fonts.googleapis.com/css2?family=Inter:wght@400;500;600;700&display=swap" rel="stylesheet">
|
12
|
+
|
13
|
+
<!-- Chart.js -->
|
14
|
+
<script src="https://cdn.jsdelivr.net/npm/chart.js@4.4.0/dist/chart.umd.js" defer></script>
|
15
|
+
|
16
|
+
<!-- Theme CSS -->
|
17
|
+
<link rel="stylesheet" href="assets/css/themes.css">
|
18
|
+
|
19
|
+
<!-- Favicon -->
|
20
|
+
<link rel="icon" type="image/svg+xml" href="data:image/svg+xml,%3csvg xmlns='http://www.w3.org/2000/svg' fill='%23F97316' viewBox='0 0 24 24'%3e%3cpath d='M12 2L2 7v10c0 5.55 3.84 9.95 9 11 5.16-1.05 9-5.45 9-11V7l-10-5z'/%3e%3c/svg%3e">
|
21
|
+
</head>
|
22
|
+
<body>
|
23
|
+
<!-- Navigation Bar -->
|
24
|
+
<nav class="navbar">
|
25
|
+
<div class="navbar-container">
|
26
|
+
<!-- Header -->
|
27
|
+
<div class="navbar-header">
|
28
|
+
<a href="#" class="navbar-brand">
|
29
|
+
<div class="navbar-brand-icon">
|
30
|
+
<svg width="20" height="20" fill="currentColor" viewBox="0 0 24 24">
|
31
|
+
<path d="M12 2L2 7v10c0 5.55 3.84 9.95 9 11 5.16-1.05 9-5.45 9-11V7l-10-5z"/>
|
32
|
+
</svg>
|
33
|
+
</div>
|
34
|
+
SerialBench
|
35
|
+
</a>
|
36
|
+
|
37
|
+
<div class="navbar-controls">
|
38
|
+
<button class="theme-toggle" title="Toggle theme">
|
39
|
+
<svg width="20" height="20" fill="none" stroke="currentColor" viewBox="0 0 24 24">
|
40
|
+
<circle cx="12" cy="12" r="5"></circle>
|
41
|
+
<line x1="12" y1="1" x2="12" y2="3"></line>
|
42
|
+
<line x1="12" y1="21" x2="12" y2="23"></line>
|
43
|
+
<line x1="4.22" y1="4.22" x2="5.64" y2="5.64"></line>
|
44
|
+
<line x1="18.36" y1="18.36" x2="19.78" y2="19.78"></line>
|
45
|
+
<line x1="1" y1="12" x2="3" y2="12"></line>
|
46
|
+
<line x1="21" y1="12" x2="23" y2="12"></line>
|
47
|
+
<line x1="4.22" y1="19.78" x2="5.64" y2="18.36"></line>
|
48
|
+
<line x1="18.36" y1="5.64" x2="19.78" y2="4.22"></line>
|
49
|
+
</svg>
|
50
|
+
</button>
|
51
|
+
</div>
|
52
|
+
</div>
|
53
|
+
|
54
|
+
<!-- Filter Bar -->
|
55
|
+
<div class="filter-bar">
|
56
|
+
<div class="filter-container">
|
57
|
+
<!-- Platform Filter -->
|
58
|
+
<div class="filter-group">
|
59
|
+
<label class="filter-label" for="platform-filter">Platform:</label>
|
60
|
+
<div class="custom-select">
|
61
|
+
<select id="platform-filter">
|
62
|
+
<option value="">All Platforms</option>
|
63
|
+
</select>
|
64
|
+
</div>
|
65
|
+
</div>
|
66
|
+
|
67
|
+
<!-- Ruby Type Filter -->
|
68
|
+
<div class="filter-group">
|
69
|
+
<label class="filter-label" for="ruby-type-filter">Ruby Type:</label>
|
70
|
+
<div class="custom-select">
|
71
|
+
<select id="ruby-type-filter">
|
72
|
+
<option value="">All Types</option>
|
73
|
+
</select>
|
74
|
+
</div>
|
75
|
+
</div>
|
76
|
+
|
77
|
+
<!-- Ruby Version Filter -->
|
78
|
+
<div class="filter-group">
|
79
|
+
<label class="filter-label" for="ruby-version-filter">Version:</label>
|
80
|
+
<div class="custom-select">
|
81
|
+
<select id="ruby-version-filter">
|
82
|
+
<option value="">All Versions</option>
|
83
|
+
</select>
|
84
|
+
</div>
|
85
|
+
</div>
|
86
|
+
|
87
|
+
<!-- Format Tabs -->
|
88
|
+
<div class="format-tabs">
|
89
|
+
<button class="format-tab active" data-format="xml">XML</button>
|
90
|
+
<button class="format-tab" data-format="json">JSON</button>
|
91
|
+
<button class="format-tab" data-format="yaml">YAML</button>
|
92
|
+
<button class="format-tab" data-format="toml">TOML</button>
|
93
|
+
</div>
|
94
|
+
</div>
|
95
|
+
</div>
|
96
|
+
</div>
|
97
|
+
</nav>
|
98
|
+
|
99
|
+
<!-- Main Content -->
|
100
|
+
<main class="main-content">
|
101
|
+
<!-- Dashboard Header -->
|
102
|
+
<header class="dashboard-header">
|
103
|
+
<h1>Performance Dashboard</h1>
|
104
|
+
<p class="dashboard-subtitle">
|
105
|
+
Comprehensive serialization performance analysis across formats, platforms, and Ruby versions
|
106
|
+
</p>
|
107
|
+
<div class="dashboard-meta">
|
108
|
+
<span><strong>Generated:</strong> {{ metadata.timestamp | default: "Unknown" }}</span>
|
109
|
+
<span><strong>Ruby Versions:</strong> {{ metadata.ruby_versions | join: ", " | default: "Unknown" }}</span>
|
110
|
+
<span><strong>Platforms:</strong> {{ metadata.platforms | join: ", " | default: "Unknown" }}</span>
|
111
|
+
</div>
|
112
|
+
</header>
|
113
|
+
|
114
|
+
<!-- Charts Grid -->
|
115
|
+
<section class="dashboard-grid">
|
116
|
+
<!-- Parsing Performance Chart -->
|
117
|
+
<div class="chart-card fade-in-up">
|
118
|
+
<div class="chart-header">
|
119
|
+
<h2 class="chart-title">Parsing Performance</h2>
|
120
|
+
<p class="chart-subtitle">Operations per second across different file sizes</p>
|
121
|
+
</div>
|
122
|
+
<div class="chart-container">
|
123
|
+
<canvas id="chart-parsing"></canvas>
|
124
|
+
</div>
|
125
|
+
</div>
|
126
|
+
|
127
|
+
<!-- Generation Performance Chart -->
|
128
|
+
<div class="chart-card fade-in-up">
|
129
|
+
<div class="chart-header">
|
130
|
+
<h2 class="chart-title">Generation Performance</h2>
|
131
|
+
<p class="chart-subtitle">Serialization speed across different file sizes</p>
|
132
|
+
</div>
|
133
|
+
<div class="chart-container">
|
134
|
+
<canvas id="chart-generation"></canvas>
|
135
|
+
</div>
|
136
|
+
</div>
|
137
|
+
|
138
|
+
<!-- Memory Usage Chart -->
|
139
|
+
<div class="chart-card fade-in-up">
|
140
|
+
<div class="chart-header">
|
141
|
+
<h2 class="chart-title">Memory Usage</h2>
|
142
|
+
<p class="chart-subtitle">Memory consumption during operations</p>
|
143
|
+
</div>
|
144
|
+
<div class="chart-container">
|
145
|
+
<canvas id="chart-memory"></canvas>
|
146
|
+
</div>
|
147
|
+
</div>
|
148
|
+
|
149
|
+
<!-- Streaming Performance Chart -->
|
150
|
+
<div class="chart-card fade-in-up">
|
151
|
+
<div class="chart-header">
|
152
|
+
<h2 class="chart-title">Streaming Performance</h2>
|
153
|
+
<p class="chart-subtitle">Streaming operations performance</p>
|
154
|
+
</div>
|
155
|
+
<div class="chart-container">
|
156
|
+
<canvas id="chart-streaming"></canvas>
|
157
|
+
</div>
|
158
|
+
</div>
|
159
|
+
</section>
|
160
|
+
|
161
|
+
<!-- Environment Information -->
|
162
|
+
<section class="environment-section fade-in-up">
|
163
|
+
<h2 class="summary-title">Environment Information</h2>
|
164
|
+
<div class="environment-grid" id="environment-info">
|
165
|
+
<!-- Environment cards will be populated by JavaScript -->
|
166
|
+
</div>
|
167
|
+
</section>
|
168
|
+
</main>
|
169
|
+
|
170
|
+
<!-- Embedded Data -->
|
171
|
+
<script>
|
172
|
+
window.benchmarkData = {{ data }};
|
173
|
+
</script>
|
174
|
+
|
175
|
+
<!-- JavaScript -->
|
176
|
+
<script src="assets/js/dashboard.js" defer></script>
|
177
|
+
|
178
|
+
<!-- Loading indicator -->
|
179
|
+
<style>
|
180
|
+
.loading-overlay {
|
181
|
+
position: fixed;
|
182
|
+
top: 0;
|
183
|
+
left: 0;
|
184
|
+
right: 0;
|
185
|
+
bottom: 0;
|
186
|
+
background: var(--bg-primary);
|
187
|
+
display: flex;
|
188
|
+
align-items: center;
|
189
|
+
justify-content: center;
|
190
|
+
z-index: 9999;
|
191
|
+
transition: opacity 0.3s ease;
|
192
|
+
}
|
193
|
+
|
194
|
+
.loading-spinner {
|
195
|
+
width: 40px;
|
196
|
+
height: 40px;
|
197
|
+
border: 3px solid var(--border-primary);
|
198
|
+
border-top: 3px solid var(--accent-primary);
|
199
|
+
border-radius: 50%;
|
200
|
+
animation: spin 1s linear infinite;
|
201
|
+
}
|
202
|
+
|
203
|
+
@keyframes spin {
|
204
|
+
0% { transform: rotate(0deg); }
|
205
|
+
100% { transform: rotate(360deg); }
|
206
|
+
}
|
207
|
+
|
208
|
+
.dashboard-header {
|
209
|
+
text-align: center;
|
210
|
+
margin-bottom: var(--space-2xl);
|
211
|
+
padding: var(--space-xl) 0;
|
212
|
+
}
|
213
|
+
|
214
|
+
.dashboard-header h1 {
|
215
|
+
font-size: 2.5rem;
|
216
|
+
font-weight: 700;
|
217
|
+
color: var(--text-primary);
|
218
|
+
margin-bottom: var(--space-md);
|
219
|
+
background: var(--gradient-primary);
|
220
|
+
-webkit-background-clip: text;
|
221
|
+
-webkit-text-fill-color: transparent;
|
222
|
+
background-clip: text;
|
223
|
+
}
|
224
|
+
|
225
|
+
.dashboard-subtitle {
|
226
|
+
font-size: 1.125rem;
|
227
|
+
color: var(--text-secondary);
|
228
|
+
margin-bottom: var(--space-lg);
|
229
|
+
max-width: 600px;
|
230
|
+
margin-left: auto;
|
231
|
+
margin-right: auto;
|
232
|
+
}
|
233
|
+
|
234
|
+
.dashboard-meta {
|
235
|
+
display: flex;
|
236
|
+
justify-content: center;
|
237
|
+
gap: var(--space-lg);
|
238
|
+
flex-wrap: wrap;
|
239
|
+
font-size: 0.875rem;
|
240
|
+
color: var(--text-muted);
|
241
|
+
}
|
242
|
+
|
243
|
+
@media (max-width: 768px) {
|
244
|
+
.dashboard-header h1 {
|
245
|
+
font-size: 2rem;
|
246
|
+
}
|
247
|
+
|
248
|
+
.dashboard-meta {
|
249
|
+
flex-direction: column;
|
250
|
+
gap: var(--space-sm);
|
251
|
+
}
|
252
|
+
}
|
253
|
+
</style>
|
254
|
+
|
255
|
+
<div class="loading-overlay" id="loading-overlay">
|
256
|
+
<div class="loading-spinner"></div>
|
257
|
+
</div>
|
258
|
+
|
259
|
+
<script>
|
260
|
+
// Hide loading overlay once everything is loaded
|
261
|
+
window.addEventListener('load', () => {
|
262
|
+
const overlay = document.getElementById('loading-overlay');
|
263
|
+
if (overlay) {
|
264
|
+
overlay.style.opacity = '0';
|
265
|
+
setTimeout(() => overlay.remove(), 300);
|
266
|
+
}
|
267
|
+
});
|
268
|
+
|
269
|
+
// Fallback to hide loading after 5 seconds
|
270
|
+
setTimeout(() => {
|
271
|
+
const overlay = document.getElementById('loading-overlay');
|
272
|
+
if (overlay) {
|
273
|
+
overlay.style.opacity = '0';
|
274
|
+
setTimeout(() => overlay.remove(), 300);
|
275
|
+
}
|
276
|
+
}, 5000);
|
277
|
+
</script>
|
278
|
+
</body>
|
279
|
+
</html>
|
data/lib/serialbench/version.rb
CHANGED
data/lib/serialbench.rb
CHANGED
@@ -3,40 +3,11 @@
|
|
3
3
|
require_relative 'serialbench/version'
|
4
4
|
require_relative 'serialbench/serializers'
|
5
5
|
require_relative 'serialbench/benchmark_runner'
|
6
|
-
require_relative 'serialbench/result_merger'
|
7
6
|
require_relative 'serialbench/cli'
|
8
|
-
require_relative 'serialbench/result_formatter'
|
9
|
-
require_relative 'serialbench/chart_generator'
|
10
7
|
require_relative 'serialbench/memory_profiler'
|
8
|
+
require_relative 'serialbench/models'
|
9
|
+
require_relative 'serialbench/site_generator'
|
11
10
|
|
12
11
|
module Serialbench
|
13
12
|
class Error < StandardError; end
|
14
|
-
|
15
|
-
# Supported serialization formats
|
16
|
-
FORMATS = %i[xml json toml].freeze
|
17
|
-
|
18
|
-
def self.run_benchmarks(formats: FORMATS, options: {})
|
19
|
-
runner = BenchmarkRunner.new(formats: formats, **options)
|
20
|
-
runner.run_all_benchmarks
|
21
|
-
end
|
22
|
-
|
23
|
-
def self.available_serializers(format = nil)
|
24
|
-
runner = BenchmarkRunner.new
|
25
|
-
if format
|
26
|
-
runner.serializers_for_format(format)
|
27
|
-
else
|
28
|
-
runner.all_serializers
|
29
|
-
end
|
30
|
-
end
|
31
|
-
|
32
|
-
def self.generate_reports(results)
|
33
|
-
result_merger = Serialbench::ResultMerger.new
|
34
|
-
result_merger.generate_all_reports(results)
|
35
|
-
end
|
36
|
-
|
37
|
-
def self.generate_reports_from_data(data_file)
|
38
|
-
require 'json'
|
39
|
-
data = JSON.parse(File.read(data_file), symbolize_names: true)
|
40
|
-
generate_reports(data)
|
41
|
-
end
|
42
13
|
end
|
data/serialbench.gemspec
CHANGED
@@ -32,18 +32,20 @@ Gem::Specification.new do |spec|
|
|
32
32
|
|
33
33
|
# Runtime dependencies
|
34
34
|
spec.add_dependency 'benchmark-ips'
|
35
|
+
spec.add_dependency 'lutaml-model'
|
35
36
|
spec.add_dependency 'memory_profiler'
|
36
37
|
spec.add_dependency 'thor'
|
37
38
|
|
38
39
|
# Reporting dependencies
|
39
40
|
spec.add_dependency 'csv' # Required from Ruby 3.4+
|
41
|
+
spec.add_dependency 'liquid' # Template engine for HTML reports
|
40
42
|
|
41
43
|
# XML serializers
|
42
|
-
spec.add_dependency 'rexml' # needed for Ruby 3.4+
|
43
44
|
spec.add_dependency 'libxml-ruby'
|
44
45
|
spec.add_dependency 'nokogiri'
|
45
46
|
spec.add_dependency 'oga'
|
46
47
|
spec.add_dependency 'ox'
|
48
|
+
spec.add_dependency 'rexml' # needed for Ruby 3.4+
|
47
49
|
|
48
50
|
# JSON serializers
|
49
51
|
spec.add_dependency 'oj'
|
@@ -56,4 +58,5 @@ Gem::Specification.new do |spec|
|
|
56
58
|
# TOML serializers
|
57
59
|
spec.add_dependency 'tomlib'
|
58
60
|
spec.add_dependency 'toml-rb'
|
61
|
+
spec.add_dependency 'tomlrb'
|
59
62
|
end
|