2cd40ea1 Andy McCall 1 month ago ↶
1
# Design Document
2
3
## Overview
4
5
This design extends the existing ` bin/checksum.rs` tool with benchmark functionality through a new ` -b` flag. The benchmark mode will measure CRC performance using either user-provided data (files/strings) or randomly generated data, reporting throughput in GiB/s along with the acceleration target used.
6
7
The design maintains backward compatibility while adding a clean benchmark interface that leverages existing patterns from the ` benches/benchmark.rs` implementation.
8
9
## Architecture
10
11
### Command Line Interface
12
13
The tool will extend the existing argument parsing to support:
14
- ` -b` : Enable benchmark mode
15
- ` --size <bytes>` : Specify data size for random generation (when no file/string provided)
16
- ` --duration <seconds>` : Benchmark duration as floating-point seconds (default: 10.0)
17
- Existing ` -a <algorithm>` : CRC algorithm (required in benchmark mode)
18
- Existing ` -f <file>` or ` -s <string>` : Optional data source for benchmarking
19
20
### Data Flow
21
22
```
23
User Input → Argument Parsing → Mode Detection → Benchmark Execution → Results Display
24
↓
25
[Normal Checksum Mode]
26
↓
27
[Existing Functionality]
28
```
29
30
In benchmark mode:
31
1. Parse and validate benchmark parameters
32
2. Determine data source (file, string, or generated)
33
3. For string/generated data: Load/generate test data once; For file data: use file path directly
34
4. Run benchmark loop for specified duration using appropriate checksum function
35
5. Calculate and display results
36
37
## Components and Interfaces
38
39
### Enhanced Config Structure
40
41
``` rust
42
#[derive(Debug)]
43
struct Config {
44
algorithm: String,
45
file: Option<String>,
46
string: Option<String>,
47
format: OutputFormat,
48
benchmark: Option<BenchmarkConfig>,
49
}
50
51
#[derive(Debug)]
52
struct BenchmarkConfig {
53
size: Option<usize>,
54
duration: f64,
55
}
56
```
57
58
### Benchmark Execution Module
59
60
``` rust
61
enum BenchmarkData {
62
InMemory(Vec<u8>),
63
File(String),
64
}
65
66
struct BenchmarkRunner {
67
algorithm: CrcAlgorithm,
68
data: BenchmarkData,
69
duration: f64,
70
}
71
72
impl BenchmarkRunner {
73
fn new(algorithm: CrcAlgorithm, data: BenchmarkData, duration: f64) -> Self
74
fn run(&self) -> BenchmarkResult
75
}
76
77
struct BenchmarkResult {
78
iterations: u64,
79
elapsed_seconds: f64,
80
throughput_gibs: f64,
81
time_per_iteration_nanos: f64,
82
acceleration_target: String,
83
data_size: u64,
84
}
85
```
86
87
### Data Generation
88
89
The benchmark will reuse the random data generation pattern from ` benches/benchmark.rs` :
90
91
``` rust
92
fn generate_random_data(size: usize) -> Vec<u8> {
93
let mut rng = rand::rng();
94
let mut buf = vec![0u8; size];
95
rng.fill_bytes(&mut buf);
96
buf
97
}
98
```
99
100
## Data Models
101
102
### Input Data Sources
103
104
1. ** File Input** : Use ` checksum_file()` function to benchmark the entire file I/O and checksum stack
105
2. ** String Input** : Use string bytes directly with in-memory ` checksum()` function
106
3. ** Generated Data** : Create random data of specified size using ` rand::RngCore::fill_bytes()` and use in-memory ` checksum()` function
107
108
### Benchmark Metrics
109
110
- ** Iterations** : Number of checksum calculations performed
111
- ** Elapsed Time** : Actual benchmark duration in seconds
112
- ** Throughput** : Calculated as ` (data_size * iterations) / elapsed_time / (1024^3)` GiB/s
113
- ** Acceleration Target** : Result from ` crc_fast::get_calculator_target(algorithm)`
114
115
## Error Handling
116
117
### Validation Errors
118
119
- Invalid algorithm names (reuse existing validation)
120
- Invalid size parameters (non-positive values)
121
- Invalid duration parameters (non-positive values)
122
- File read errors (reuse existing error handling)
123
124
### Runtime Errors
125
126
- Memory allocation failures for large data sizes
127
- Timer precision issues (fallback to alternative timing methods)
128
129
### Error Messages
130
131
All errors will follow the existing pattern of displaying the error message followed by usage information.
132
133
## Testing Strategy
134
135
### Unit Tests
136
137
- Argument parsing validation for benchmark flags
138
- BenchmarkConfig creation and validation
139
- Data generation with various sizes
140
- Throughput calculation accuracy
141
142
### Integration Tests
143
144
- End-to-end benchmark execution with different algorithms
145
- File and string input handling in benchmark mode
146
- Error handling for invalid parameters
147
- Backward compatibility verification
148
149
### Performance Validation
150
151
- Verify benchmark results are reasonable (within expected ranges)
152
- Compare with existing ` benches/benchmark.rs` results for consistency
153
- Test with various data sizes to ensure linear scaling
154
155
## Implementation Notes
156
157
### Timing Mechanism
158
159
Use ` std::time::Instant` for high-precision timing, with different approaches for different data sources:
160
161
``` rust
162
let start = std::time::Instant::now();
163
let mut iterations = 0u64;
164
165
while start.elapsed().as_secs_f64() < duration {
166
match &self.data {
167
BenchmarkData::InMemory(data) => {
168
std::hint::black_box(checksum(algorithm, data));
169
}
170
BenchmarkData::File(filename) => {
171
std::hint::black_box(checksum_file(algorithm, filename, None).unwrap());
172
}
173
}
174
iterations += 1;
175
}
176
177
let elapsed = start.elapsed().as_secs_f64();
178
```
179
180
### Memory Considerations
181
182
- Pre-allocate test data once before benchmark loop
183
- Use ` std::hint::black_box()` to prevent compiler optimizations
184
- Consider memory alignment for optimal performance (optional enhancement)
185
186
### Output Format
187
188
```
189
Algorithm: CRC-32/ISCSI
190
Acceleration Target: aarch64-neon-sha3
191
Data Size: 1,048,576 bytes (1.0 MiB)
192
Duration: 10.00 seconds
193
Iterations: 12,345
194
Throughput: 45.67 GiB/s
195
Time per iteration: 810.2 μs
196
```
197
198
### Default Values
199
200
- ** Size** : 1,048,576 bytes (1 MiB)
201
- ** Duration** : 10.0 seconds
202
- ** Algorithm** : Must be specified via ` -a` flag (no default)