serialbench 0.1.0 → 0.1.1
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 +173 -30
- data/.github/workflows/ci.yml +3 -3
- data/.github/workflows/docker.yml +246 -0
- data/.github/workflows/release.yml +25 -0
- data/Gemfile +5 -30
- data/README.adoc +962 -134
- data/config/ci.yml +22 -0
- data/config/full.yml +30 -0
- data/docker/Dockerfile.benchmark +31 -0
- data/docker/README.md +214 -0
- data/docker/run-benchmarks.sh +356 -0
- data/lib/serialbench/benchmark_runner.rb +82 -0
- data/lib/serialbench/cli.rb +201 -9
- data/lib/serialbench/result_merger.rb +5 -5
- data/lib/serialbench/serializers/json/rapidjson_serializer.rb +50 -0
- data/lib/serialbench/serializers/json/yajl_serializer.rb +6 -2
- data/lib/serialbench/serializers/xml/nokogiri_serializer.rb +21 -3
- data/lib/serialbench/serializers/xml/rexml_serializer.rb +32 -2
- data/lib/serialbench/serializers/yaml/base_yaml_serializer.rb +55 -0
- data/lib/serialbench/serializers/yaml/psych_serializer.rb +54 -0
- data/lib/serialbench/serializers/yaml/syck_serializer.rb +65 -0
- data/lib/serialbench/serializers.rb +11 -0
- data/lib/serialbench/version.rb +1 -1
- data/serialbench.gemspec +25 -17
- metadata +113 -46
data/config/ci.yml
ADDED
@@ -0,0 +1,22 @@
|
|
1
|
+
# Configuration for CI/GitHub Actions - Memory-safe settings
|
2
|
+
# Only runs small data sizes to avoid memory constraints
|
3
|
+
|
4
|
+
data_sizes:
|
5
|
+
- small
|
6
|
+
|
7
|
+
formats:
|
8
|
+
- xml
|
9
|
+
- json
|
10
|
+
- yaml
|
11
|
+
- toml
|
12
|
+
|
13
|
+
iterations:
|
14
|
+
small: 20
|
15
|
+
medium: 5
|
16
|
+
large: 2
|
17
|
+
|
18
|
+
# Disable memory profiling in CI to reduce memory usage
|
19
|
+
memory_profiling: false
|
20
|
+
|
21
|
+
# Reduce warmup iterations for faster CI
|
22
|
+
warmup_iterations: 2
|
data/config/full.yml
ADDED
@@ -0,0 +1,30 @@
|
|
1
|
+
# Configuration for comprehensive benchmarks - Full testing with all data sizes
|
2
|
+
# Used by Docker script for complete performance analysis
|
3
|
+
|
4
|
+
data_sizes:
|
5
|
+
- small
|
6
|
+
- medium
|
7
|
+
- large
|
8
|
+
|
9
|
+
formats:
|
10
|
+
- xml
|
11
|
+
- json
|
12
|
+
- yaml
|
13
|
+
- toml
|
14
|
+
|
15
|
+
iterations:
|
16
|
+
small: 20
|
17
|
+
medium: 5
|
18
|
+
large: 2
|
19
|
+
|
20
|
+
# Enable memory profiling for comprehensive analysis
|
21
|
+
memory_profiling: true
|
22
|
+
|
23
|
+
# Standard warmup iterations
|
24
|
+
warmup_iterations: 3
|
25
|
+
|
26
|
+
# Enable streaming benchmarks where supported
|
27
|
+
streaming_benchmarks: true
|
28
|
+
|
29
|
+
# Generate detailed reports
|
30
|
+
detailed_reports: true
|
@@ -0,0 +1,31 @@
|
|
1
|
+
# Multi-stage Dockerfile for Ruby serialization benchmarks
|
2
|
+
# Supports multiple Ruby versions for comprehensive testing
|
3
|
+
|
4
|
+
ARG RUBY_VERSION=3.3
|
5
|
+
FROM ruby:${RUBY_VERSION}
|
6
|
+
|
7
|
+
# Install system dependencies for XML libraries
|
8
|
+
RUN apt-get update && apt-get install -y \
|
9
|
+
libxml2-dev \
|
10
|
+
libxslt1-dev \
|
11
|
+
build-essential \
|
12
|
+
&& rm -rf /var/lib/apt/lists/*
|
13
|
+
|
14
|
+
# Set working directory
|
15
|
+
WORKDIR /app
|
16
|
+
|
17
|
+
# Copy the entire application (gemspec needs full context)
|
18
|
+
COPY . .
|
19
|
+
|
20
|
+
# Update bundler and configure bundle for cross-platform compatibility
|
21
|
+
RUN gem install bundler:2.5.22 && \
|
22
|
+
bundle config set --local deployment 'false' && \
|
23
|
+
bundle config set --local path '/usr/local/bundle' && \
|
24
|
+
bundle config set --local force_ruby_platform true && \
|
25
|
+
bundle install --jobs 4 --retry 3
|
26
|
+
|
27
|
+
# Create results directory
|
28
|
+
RUN mkdir -p /app/results
|
29
|
+
|
30
|
+
# Default command runs parsing and generation benchmarks (memory benchmarks disabled due to hanging in Docker)
|
31
|
+
CMD ["bundle", "exec", "ruby", "exe/serialbench", "benchmark", "--formats", "xml", "json", "yaml", "toml", "--iterations", "1", "--warmup", "0", "--parsing_only"]
|
data/docker/README.md
ADDED
@@ -0,0 +1,214 @@
|
|
1
|
+
# Serialbench Docker Setup
|
2
|
+
|
3
|
+
This directory contains Docker infrastructure for running Serialbench across multiple Ruby versions in isolated environments.
|
4
|
+
|
5
|
+
## Files
|
6
|
+
|
7
|
+
- `Dockerfile.benchmark` - Multi-stage Dockerfile for building benchmark environments
|
8
|
+
- `run-benchmarks.sh` - Automated script for running benchmarks across multiple Ruby versions
|
9
|
+
|
10
|
+
## Quick Start
|
11
|
+
|
12
|
+
### Prerequisites
|
13
|
+
|
14
|
+
- Docker installed and running
|
15
|
+
- Bash shell (Linux/macOS/WSL)
|
16
|
+
|
17
|
+
### Running Multi-Ruby Benchmarks
|
18
|
+
|
19
|
+
```bash
|
20
|
+
# From the project root directory
|
21
|
+
./docker/run-benchmarks.sh
|
22
|
+
```
|
23
|
+
|
24
|
+
This will:
|
25
|
+
1. Build Docker images for Ruby 3.1, 3.2, 3.3, and 3.4 (skipping existing images)
|
26
|
+
2. Run comprehensive benchmarks in each environment
|
27
|
+
3. Merge results from all Ruby versions
|
28
|
+
4. Generate GitHub Pages with comparative results
|
29
|
+
|
30
|
+
#### Force Rebuild Images
|
31
|
+
|
32
|
+
To force rebuild all Docker images (even if they already exist):
|
33
|
+
|
34
|
+
```bash
|
35
|
+
# Force rebuild all images
|
36
|
+
./docker/run-benchmarks.sh --force-rebuild
|
37
|
+
|
38
|
+
# Or use the short form
|
39
|
+
./docker/run-benchmarks.sh -f
|
40
|
+
```
|
41
|
+
|
42
|
+
This is useful when:
|
43
|
+
- Dependencies have been updated
|
44
|
+
- Dockerfile has been modified
|
45
|
+
- You want to ensure fresh builds
|
46
|
+
- Troubleshooting build-related issues
|
47
|
+
|
48
|
+
#### Command Line Options
|
49
|
+
|
50
|
+
```bash
|
51
|
+
# Show help and available options
|
52
|
+
./docker/run-benchmarks.sh --help
|
53
|
+
|
54
|
+
# Available options:
|
55
|
+
# --force-rebuild, -f Force rebuild of Docker images even if they exist
|
56
|
+
# --help, -h Show help message
|
57
|
+
```
|
58
|
+
|
59
|
+
### Results
|
60
|
+
|
61
|
+
Results are saved in `docker-results/`:
|
62
|
+
```
|
63
|
+
docker-results/
|
64
|
+
├── ruby-3.1/ # Ruby 3.1 results
|
65
|
+
├── ruby-3.2/ # Ruby 3.2 results
|
66
|
+
├── ruby-3.3/ # Ruby 3.3 results
|
67
|
+
├── ruby-3.4/ # Ruby 3.4 results
|
68
|
+
├── merged/ # Merged results from all versions
|
69
|
+
└── docs/ # GitHub Pages site
|
70
|
+
```
|
71
|
+
|
72
|
+
## Manual Docker Usage
|
73
|
+
|
74
|
+
### Build Image for Specific Ruby Version
|
75
|
+
|
76
|
+
```bash
|
77
|
+
docker build \
|
78
|
+
--build-arg RUBY_VERSION=3.3 \
|
79
|
+
-t serialbench:ruby-3.3 \
|
80
|
+
-f docker/Dockerfile.benchmark \
|
81
|
+
.
|
82
|
+
```
|
83
|
+
|
84
|
+
### Run Benchmarks
|
85
|
+
|
86
|
+
```bash
|
87
|
+
# Create results directory
|
88
|
+
mkdir -p results
|
89
|
+
|
90
|
+
# Run benchmarks
|
91
|
+
docker run \
|
92
|
+
--rm \
|
93
|
+
-v $(pwd)/results:/app/results \
|
94
|
+
serialbench:ruby-3.3
|
95
|
+
```
|
96
|
+
|
97
|
+
### Custom Configuration
|
98
|
+
|
99
|
+
```bash
|
100
|
+
# Use custom config file
|
101
|
+
docker run \
|
102
|
+
--rm \
|
103
|
+
-v $(pwd)/results:/app/results \
|
104
|
+
-v $(pwd)/config:/app/config \
|
105
|
+
serialbench:ruby-3.3 \
|
106
|
+
bundle exec serialbench benchmark --config config/ci.yml
|
107
|
+
```
|
108
|
+
|
109
|
+
## Supported Ruby Versions
|
110
|
+
|
111
|
+
- Ruby 3.1
|
112
|
+
- Ruby 3.2
|
113
|
+
- Ruby 3.3
|
114
|
+
- Ruby 3.4
|
115
|
+
|
116
|
+
## Environment Variables
|
117
|
+
|
118
|
+
The Docker images support these environment variables:
|
119
|
+
|
120
|
+
- `BUNDLE_PATH` - Bundle installation path
|
121
|
+
- `BUNDLE_BIN` - Bundle binary path
|
122
|
+
- `PATH` - System PATH including bundle binaries
|
123
|
+
|
124
|
+
## Troubleshooting
|
125
|
+
|
126
|
+
### Build Failures
|
127
|
+
|
128
|
+
Check build logs in `docker-results/build-ruby-X.X.log`:
|
129
|
+
|
130
|
+
```bash
|
131
|
+
cat docker-results/build-ruby-3.3.log
|
132
|
+
```
|
133
|
+
|
134
|
+
### Runtime Failures
|
135
|
+
|
136
|
+
Check benchmark logs in `docker-results/ruby-X.X/benchmark.log`:
|
137
|
+
|
138
|
+
```bash
|
139
|
+
cat docker-results/ruby-3.3/benchmark.log
|
140
|
+
```
|
141
|
+
|
142
|
+
### Docker Issues
|
143
|
+
|
144
|
+
Ensure Docker is running:
|
145
|
+
```bash
|
146
|
+
docker info
|
147
|
+
```
|
148
|
+
|
149
|
+
Clean up Docker resources:
|
150
|
+
```bash
|
151
|
+
# Remove all serialbench images
|
152
|
+
docker rmi $(docker images serialbench -q)
|
153
|
+
|
154
|
+
# Remove all containers
|
155
|
+
docker container prune
|
156
|
+
```
|
157
|
+
|
158
|
+
## Customization
|
159
|
+
|
160
|
+
### Adding Ruby Versions
|
161
|
+
|
162
|
+
Edit `RUBY_VERSIONS` array in `run-benchmarks.sh`:
|
163
|
+
|
164
|
+
```bash
|
165
|
+
RUBY_VERSIONS=("3.1" "3.2" "3.3" "3.4" "head")
|
166
|
+
```
|
167
|
+
|
168
|
+
### Custom Benchmark Configuration
|
169
|
+
|
170
|
+
Create custom config files in `config/` directory and reference them:
|
171
|
+
|
172
|
+
```bash
|
173
|
+
# In run-benchmarks.sh
|
174
|
+
CONFIG_FILE="config/custom.yml"
|
175
|
+
```
|
176
|
+
|
177
|
+
### Output Directory
|
178
|
+
|
179
|
+
Change the output directory:
|
180
|
+
|
181
|
+
```bash
|
182
|
+
# In run-benchmarks.sh
|
183
|
+
OUTPUT_DIR="my-results"
|
184
|
+
```
|
185
|
+
|
186
|
+
## Integration with CI/CD
|
187
|
+
|
188
|
+
The Docker setup integrates with GitHub Actions. See `.github/workflows/benchmark.yml` for automated benchmark runs.
|
189
|
+
|
190
|
+
### GitHub Actions Usage
|
191
|
+
|
192
|
+
```yaml
|
193
|
+
- name: Run Docker Benchmarks
|
194
|
+
run: ./docker/run-benchmarks.sh
|
195
|
+
|
196
|
+
- name: Upload Results
|
197
|
+
uses: actions/upload-artifact@v3
|
198
|
+
with:
|
199
|
+
name: benchmark-results
|
200
|
+
path: docker-results/
|
201
|
+
```
|
202
|
+
|
203
|
+
## Performance Considerations
|
204
|
+
|
205
|
+
- Each Ruby version runs in isolation
|
206
|
+
- Results are automatically merged for comparison
|
207
|
+
- Memory profiling is enabled by default
|
208
|
+
- Build caching optimizes subsequent runs
|
209
|
+
|
210
|
+
## Security
|
211
|
+
|
212
|
+
- Containers run with minimal privileges
|
213
|
+
- No network access required during benchmarks
|
214
|
+
- Results are written to mounted volumes only
|
@@ -0,0 +1,356 @@
|
|
1
|
+
#!/bin/bash
|
2
|
+
|
3
|
+
# Serialbench Docker Multi-Ruby Version Benchmark Runner
|
4
|
+
# Runs comprehensive benchmarks across multiple Ruby versions using Docker
|
5
|
+
|
6
|
+
set -e
|
7
|
+
|
8
|
+
# Configuration
|
9
|
+
RUBY_VERSIONS=("3.0" "3.1" "3.2" "3.3" "3.4")
|
10
|
+
OUTPUT_DIR="docker-results"
|
11
|
+
CONFIG_FILE="config/full.yml"
|
12
|
+
DOCKERFILE="docker/Dockerfile.benchmark"
|
13
|
+
FORCE_REBUILD=false
|
14
|
+
|
15
|
+
# Colors for output
|
16
|
+
RED='\033[0;31m'
|
17
|
+
GREEN='\033[0;32m'
|
18
|
+
YELLOW='\033[1;33m'
|
19
|
+
BLUE='\033[0;34m'
|
20
|
+
NC='\033[0m' # No Color
|
21
|
+
|
22
|
+
# Helper functions
|
23
|
+
log_info() {
|
24
|
+
echo -e "${BLUE}[INFO]${NC} $1"
|
25
|
+
}
|
26
|
+
|
27
|
+
log_success() {
|
28
|
+
echo -e "${GREEN}[SUCCESS]${NC} $1"
|
29
|
+
}
|
30
|
+
|
31
|
+
log_warning() {
|
32
|
+
echo -e "${YELLOW}[WARNING]${NC} $1"
|
33
|
+
}
|
34
|
+
|
35
|
+
log_error() {
|
36
|
+
echo -e "${RED}[ERROR]${NC} $1"
|
37
|
+
}
|
38
|
+
|
39
|
+
# Show usage information
|
40
|
+
show_usage() {
|
41
|
+
echo "Usage: $0 [OPTIONS]"
|
42
|
+
echo
|
43
|
+
echo "Run comprehensive benchmarks across multiple Ruby versions using Docker"
|
44
|
+
echo
|
45
|
+
echo "OPTIONS:"
|
46
|
+
echo " --force-rebuild, -f Force rebuild of Docker images even if they exist"
|
47
|
+
echo " --help, -h Show this help message"
|
48
|
+
echo
|
49
|
+
echo "EXAMPLES:"
|
50
|
+
echo " $0 Run benchmarks (skip building existing images)"
|
51
|
+
echo " $0 --force-rebuild Run benchmarks and rebuild all images"
|
52
|
+
echo " $0 -f Same as --force-rebuild"
|
53
|
+
echo
|
54
|
+
}
|
55
|
+
|
56
|
+
# Parse command line arguments
|
57
|
+
parse_arguments() {
|
58
|
+
while [[ $# -gt 0 ]]; do
|
59
|
+
case $1 in
|
60
|
+
--force-rebuild|-f)
|
61
|
+
FORCE_REBUILD=true
|
62
|
+
log_info "Force rebuild enabled - will rebuild all Docker images"
|
63
|
+
shift
|
64
|
+
;;
|
65
|
+
--help|-h)
|
66
|
+
show_usage
|
67
|
+
exit 0
|
68
|
+
;;
|
69
|
+
*)
|
70
|
+
log_error "Unknown option: $1"
|
71
|
+
show_usage
|
72
|
+
exit 1
|
73
|
+
;;
|
74
|
+
esac
|
75
|
+
done
|
76
|
+
}
|
77
|
+
|
78
|
+
# Check if Docker is available
|
79
|
+
check_docker() {
|
80
|
+
if ! command -v docker &> /dev/null; then
|
81
|
+
log_error "Docker is not installed or not in PATH"
|
82
|
+
exit 1
|
83
|
+
fi
|
84
|
+
|
85
|
+
if ! docker info &> /dev/null; then
|
86
|
+
log_error "Docker daemon is not running"
|
87
|
+
exit 1
|
88
|
+
fi
|
89
|
+
|
90
|
+
log_success "Docker is available"
|
91
|
+
}
|
92
|
+
|
93
|
+
# Clean up previous results
|
94
|
+
cleanup_results() {
|
95
|
+
if [ -d "$OUTPUT_DIR" ]; then
|
96
|
+
log_info "Cleaning up previous results in $OUTPUT_DIR"
|
97
|
+
rm -rf "$OUTPUT_DIR"
|
98
|
+
fi
|
99
|
+
mkdir -p "$OUTPUT_DIR"
|
100
|
+
}
|
101
|
+
|
102
|
+
# Build Docker image for specific Ruby version
|
103
|
+
build_image() {
|
104
|
+
local ruby_version=$1
|
105
|
+
local image_name="serialbench:ruby-${ruby_version}"
|
106
|
+
|
107
|
+
# Check if image already exists (unless force rebuild is enabled)
|
108
|
+
if [ "$FORCE_REBUILD" = false ] && docker image inspect "${image_name}" >/dev/null 2>&1; then
|
109
|
+
log_success "Image ${image_name} already exists, skipping build"
|
110
|
+
return 0
|
111
|
+
fi
|
112
|
+
|
113
|
+
if [ "$FORCE_REBUILD" = true ] && docker image inspect "${image_name}" >/dev/null 2>&1; then
|
114
|
+
log_info "Force rebuild enabled, removing existing image ${image_name}..."
|
115
|
+
docker rmi "${image_name}" >/dev/null 2>&1 || true
|
116
|
+
fi
|
117
|
+
|
118
|
+
log_info "Building Docker image for Ruby ${ruby_version}..."
|
119
|
+
|
120
|
+
if docker build \
|
121
|
+
--build-arg RUBY_VERSION="${ruby_version}" \
|
122
|
+
-t "${image_name}" \
|
123
|
+
-f "${DOCKERFILE}" \
|
124
|
+
. > "${OUTPUT_DIR}/build-ruby-${ruby_version}.log" 2>&1; then
|
125
|
+
log_success "Built image ${image_name}"
|
126
|
+
return 0
|
127
|
+
else
|
128
|
+
log_error "Failed to build image for Ruby ${ruby_version}"
|
129
|
+
log_error "Check ${OUTPUT_DIR}/build-ruby-${ruby_version}.log for details"
|
130
|
+
return 1
|
131
|
+
fi
|
132
|
+
}
|
133
|
+
|
134
|
+
# Run benchmarks for specific Ruby version
|
135
|
+
run_benchmark() {
|
136
|
+
local ruby_version=$1
|
137
|
+
local image_name="serialbench:ruby-${ruby_version}"
|
138
|
+
local container_name="serialbench-ruby-${ruby_version}"
|
139
|
+
local result_dir="${OUTPUT_DIR}/ruby-${ruby_version}"
|
140
|
+
|
141
|
+
log_info "Running benchmarks for Ruby ${ruby_version}..."
|
142
|
+
|
143
|
+
# Create result directory
|
144
|
+
mkdir -p "${result_dir}"
|
145
|
+
|
146
|
+
# Run container with benchmark
|
147
|
+
if docker run \
|
148
|
+
--name "${container_name}" \
|
149
|
+
--rm \
|
150
|
+
-v "$(pwd)/${result_dir}:/app/results" \
|
151
|
+
"${image_name}" \
|
152
|
+
> "${result_dir}/benchmark.log" 2>&1; then
|
153
|
+
log_success "Completed benchmarks for Ruby ${ruby_version}"
|
154
|
+
return 0
|
155
|
+
else
|
156
|
+
log_error "Failed to run benchmarks for Ruby ${ruby_version}"
|
157
|
+
log_error "Check ${result_dir}/benchmark.log for details"
|
158
|
+
return 1
|
159
|
+
fi
|
160
|
+
}
|
161
|
+
|
162
|
+
# Merge results from all Ruby versions
|
163
|
+
merge_results() {
|
164
|
+
log_info "Merging results from all Ruby versions..."
|
165
|
+
|
166
|
+
local input_dirs=""
|
167
|
+
for version in "${RUBY_VERSIONS[@]}"; do
|
168
|
+
local result_dir="${OUTPUT_DIR}/ruby-${version}"
|
169
|
+
if [ -d "${result_dir}" ] && [ -f "${result_dir}/data/results.json" ]; then
|
170
|
+
input_dirs="${input_dirs} ${result_dir}"
|
171
|
+
else
|
172
|
+
log_warning "No results found for Ruby ${version}"
|
173
|
+
fi
|
174
|
+
done
|
175
|
+
|
176
|
+
if [ -n "$input_dirs" ]; then
|
177
|
+
if bundle exec serialbench merge_results ${input_dirs} "${OUTPUT_DIR}/merged"; then
|
178
|
+
log_success "Results merged successfully"
|
179
|
+
else
|
180
|
+
log_error "Failed to merge results"
|
181
|
+
return 1
|
182
|
+
fi
|
183
|
+
else
|
184
|
+
log_error "No valid results to merge"
|
185
|
+
return 1
|
186
|
+
fi
|
187
|
+
}
|
188
|
+
|
189
|
+
# Generate GitHub Pages
|
190
|
+
generate_github_pages() {
|
191
|
+
log_info "Generating GitHub Pages..."
|
192
|
+
|
193
|
+
local input_dirs=""
|
194
|
+
for version in "${RUBY_VERSIONS[@]}"; do
|
195
|
+
local result_dir="${OUTPUT_DIR}/ruby-${version}"
|
196
|
+
if [ -d "${result_dir}" ] && [ -f "${result_dir}/data/results.json" ]; then
|
197
|
+
input_dirs="${input_dirs} ${result_dir}"
|
198
|
+
fi
|
199
|
+
done
|
200
|
+
|
201
|
+
if [ -n "$input_dirs" ]; then
|
202
|
+
if bundle exec serialbench github_pages ${input_dirs} "${OUTPUT_DIR}/docs"; then
|
203
|
+
log_success "GitHub Pages generated successfully"
|
204
|
+
log_info "Open ${OUTPUT_DIR}/docs/index.html to view results"
|
205
|
+
else
|
206
|
+
log_error "Failed to generate GitHub Pages"
|
207
|
+
return 1
|
208
|
+
fi
|
209
|
+
else
|
210
|
+
log_error "No valid results for GitHub Pages generation"
|
211
|
+
return 1
|
212
|
+
fi
|
213
|
+
}
|
214
|
+
|
215
|
+
# Build all Docker images (fail fast)
|
216
|
+
build_all_images() {
|
217
|
+
local failed_builds=()
|
218
|
+
|
219
|
+
for version in "${RUBY_VERSIONS[@]}"; do
|
220
|
+
if ! build_image "${version}"; then
|
221
|
+
failed_builds+=("${version}")
|
222
|
+
fi
|
223
|
+
done
|
224
|
+
|
225
|
+
if [ ${#failed_builds[@]} -gt 0 ]; then
|
226
|
+
log_error "Failed to build images for Ruby versions: ${failed_builds[*]}"
|
227
|
+
log_error "Aborting benchmark run due to build failures"
|
228
|
+
exit 1
|
229
|
+
fi
|
230
|
+
|
231
|
+
log_success "All Docker images built successfully"
|
232
|
+
}
|
233
|
+
|
234
|
+
# Run benchmarks on all built images
|
235
|
+
run_all_benchmarks() {
|
236
|
+
local successful_runs=0
|
237
|
+
local failed_runs=()
|
238
|
+
|
239
|
+
for version in "${RUBY_VERSIONS[@]}"; do
|
240
|
+
if run_benchmark "${version}"; then
|
241
|
+
((successful_runs++))
|
242
|
+
else
|
243
|
+
failed_runs+=("${version}")
|
244
|
+
log_warning "Benchmark failed for Ruby ${version}"
|
245
|
+
fi
|
246
|
+
done
|
247
|
+
|
248
|
+
log_info "Benchmark runs completed: ${successful_runs}/${#RUBY_VERSIONS[@]} successful"
|
249
|
+
|
250
|
+
if [ ${#failed_runs[@]} -gt 0 ]; then
|
251
|
+
log_warning "Failed benchmark runs for Ruby versions: ${failed_runs[*]}"
|
252
|
+
fi
|
253
|
+
|
254
|
+
# Store results for processing phase
|
255
|
+
echo "${successful_runs}" > "${OUTPUT_DIR}/.successful_runs"
|
256
|
+
}
|
257
|
+
|
258
|
+
# Process results (fail if no successful runs)
|
259
|
+
process_results() {
|
260
|
+
local successful_runs
|
261
|
+
if [ -f "${OUTPUT_DIR}/.successful_runs" ]; then
|
262
|
+
successful_runs=$(cat "${OUTPUT_DIR}/.successful_runs")
|
263
|
+
else
|
264
|
+
successful_runs=0
|
265
|
+
fi
|
266
|
+
|
267
|
+
if [ "${successful_runs}" -eq 0 ]; then
|
268
|
+
log_error "No successful benchmark runs to process"
|
269
|
+
exit 1
|
270
|
+
fi
|
271
|
+
|
272
|
+
log_info "Processing ${successful_runs} successful benchmark results..."
|
273
|
+
|
274
|
+
if ! merge_results; then
|
275
|
+
log_error "Failed to merge results"
|
276
|
+
exit 1
|
277
|
+
fi
|
278
|
+
|
279
|
+
if ! generate_github_pages; then
|
280
|
+
log_error "Failed to generate GitHub Pages"
|
281
|
+
exit 1
|
282
|
+
fi
|
283
|
+
|
284
|
+
log_success "Results processed successfully"
|
285
|
+
}
|
286
|
+
|
287
|
+
# Print summary
|
288
|
+
print_summary() {
|
289
|
+
echo
|
290
|
+
echo "=========================================="
|
291
|
+
echo "Serialbench Docker Benchmark Summary"
|
292
|
+
echo "=========================================="
|
293
|
+
echo
|
294
|
+
|
295
|
+
for version in "${RUBY_VERSIONS[@]}"; do
|
296
|
+
local result_dir="${OUTPUT_DIR}/ruby-${version}"
|
297
|
+
if [ -f "${result_dir}/data/results.json" ]; then
|
298
|
+
echo "✅ Ruby ${version}: Completed"
|
299
|
+
else
|
300
|
+
echo "❌ Ruby ${version}: Failed"
|
301
|
+
fi
|
302
|
+
done
|
303
|
+
|
304
|
+
echo
|
305
|
+
if [ -f "${OUTPUT_DIR}/merged/merged_results.json" ]; then
|
306
|
+
echo "📊 Merged results: ${OUTPUT_DIR}/merged/merged_results.json"
|
307
|
+
fi
|
308
|
+
|
309
|
+
if [ -f "${OUTPUT_DIR}/docs/index.html" ]; then
|
310
|
+
echo "🌐 GitHub Pages: ${OUTPUT_DIR}/docs/index.html"
|
311
|
+
echo
|
312
|
+
echo "To view results, open: file://$(pwd)/${OUTPUT_DIR}/docs/index.html"
|
313
|
+
fi
|
314
|
+
|
315
|
+
echo
|
316
|
+
}
|
317
|
+
|
318
|
+
# Main execution
|
319
|
+
main() {
|
320
|
+
# Parse command line arguments first
|
321
|
+
parse_arguments "$@"
|
322
|
+
|
323
|
+
echo "=========================================="
|
324
|
+
echo "Serialbench Docker Multi-Ruby Benchmarks"
|
325
|
+
echo "=========================================="
|
326
|
+
echo
|
327
|
+
|
328
|
+
# Check prerequisites
|
329
|
+
check_docker
|
330
|
+
|
331
|
+
# Clean up
|
332
|
+
cleanup_results
|
333
|
+
|
334
|
+
# Phase 1: Build all images (fail fast)
|
335
|
+
echo
|
336
|
+
log_info "Phase 1: Building all Docker images..."
|
337
|
+
build_all_images
|
338
|
+
|
339
|
+
# Phase 2: Run all benchmarks
|
340
|
+
echo
|
341
|
+
log_info "Phase 2: Running benchmarks on all images..."
|
342
|
+
run_all_benchmarks
|
343
|
+
|
344
|
+
# Phase 3: Process results (fail if no successful runs)
|
345
|
+
echo
|
346
|
+
log_info "Phase 3: Processing results..."
|
347
|
+
process_results
|
348
|
+
|
349
|
+
# Print summary
|
350
|
+
print_summary
|
351
|
+
|
352
|
+
log_success "Docker benchmark run completed!"
|
353
|
+
}
|
354
|
+
|
355
|
+
# Run main function
|
356
|
+
main "$@"
|