png_conform 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.
@@ -0,0 +1,570 @@
1
+ = PNG Validation Benchmark Suite
2
+
3
+ == Purpose
4
+
5
+ This benchmark suite compares the performance of [`png_conform`](../README.adoc) against [`pngcheck`](https://github.com/pnggroup/pngcheck), focusing on execution time and memory usage metrics.
6
+
7
+ The benchmark suite measures real-world performance differences between the pure Ruby implementation (png_conform) and the native C implementation (pngcheck) when validating PNG files.
8
+
9
+ == Features
10
+
11
+ * *Performance Comparison*: Measures execution time and memory usage
12
+ * *Statistical Analysis*: Calculates mean, median, standard deviation, min/max
13
+ * *Multiple Output Formats*: Text, JSON, CSV, and Markdown reports
14
+ * *Configurable Testing*: YAML-based configuration for flexible benchmark runs
15
+ * *Progress Tracking*: Real-time progress indicators during execution
16
+ * *Warmup Runs*: Eliminates cold start effects for accurate measurements
17
+
18
+ == Architecture
19
+
20
+ .Benchmark System Components
21
+ [source]
22
+ ----
23
+ run_benchmark.rb (CLI)
24
+
25
+ └─► BenchmarkRunner (Orchestrator)
26
+
27
+ ├─► PngConformRunner
28
+ ├─► PngcheckRunner
29
+ ├─► MetricsCollector
30
+ └─► ReportGenerator
31
+ ----
32
+
33
+ === Component Responsibilities
34
+
35
+ `run_benchmark.rb`:: Command-line interface with option parsing
36
+ `BenchmarkRunner`:: Coordinates file discovery, tool execution, and reporting
37
+ `ToolRunner`:: Base class for tool execution with performance measurement
38
+ `PngConformRunner`:: Executes [`png_conform`](../exe/png_conform) CLI
39
+ `PngcheckRunner`:: Executes system `pngcheck` binary
40
+ `MetricsCollector`:: Gathers and analyzes performance statistics
41
+ `ReportGenerator`:: Formats output in multiple formats
42
+
43
+ == Installation
44
+
45
+ === Prerequisites
46
+
47
+ Ensure both tools are available:
48
+
49
+ [source,shell]
50
+ ----
51
+ # png_conform (from project root)
52
+ bundle install
53
+
54
+ # pngcheck (system binary)
55
+ brew install pngcheck # macOS
56
+ # or
57
+ apt-get install pngcheck # Linux
58
+ ----
59
+
60
+ === Verify Installation
61
+
62
+ [source,shell]
63
+ ----
64
+ # Check png_conform
65
+ ./exe/png_conform --version
66
+
67
+ # Check pngcheck
68
+ which pngcheck
69
+ pngcheck -h
70
+ ----
71
+
72
+ == Usage
73
+
74
+ === Basic Usage
75
+
76
+ Run default benchmark with all PNG files in the test suite:
77
+
78
+ [source,shell]
79
+ ----
80
+ ./benchmarks/run_benchmark.rb
81
+ ----
82
+
83
+ .Default benchmark output
84
+ [example]
85
+ ====
86
+ [source,shell]
87
+ ----
88
+ $ ./benchmarks/run_benchmark.rb
89
+ Initializing benchmark...
90
+ Checking tool availability...
91
+ ✓ png_conform is available
92
+ ✓ pngcheck is available
93
+
94
+ Found 177 PNG files to test
95
+
96
+ Running benchmarks...
97
+ Iterations: 3
98
+ Warmup runs: 1
99
+
100
+ Benchmarking png_conform...
101
+ [========================================] 100.0% (1062/1062) png_conform
102
+
103
+ Benchmarking pngcheck...
104
+ [========================================] 100.0% (1062/1062) pngcheck
105
+
106
+ Generating report...
107
+
108
+ ================================================================================
109
+ PNG Validation Tool Benchmark Comparison
110
+ ================================================================================
111
+
112
+ Configuration:
113
+ Files tested: 177 PNG files
114
+ Total runs: 1062
115
+
116
+ Tools:
117
+ png_conform: 531/531 successful
118
+ pngcheck: 531/531 successful
119
+
120
+ --------------------------------------------------------------------------------
121
+ PERFORMANCE SUMMARY
122
+ --------------------------------------------------------------------------------
123
+
124
+ Tool Avg Time Files/sec Peak Memory Winner
125
+ png_conform 45.2ms 22.1 45.2 MB
126
+ pngcheck 12.3ms 81.3 8.5 MB ✓
127
+
128
+ Performance Difference:
129
+ pngcheck is 3.7x faster (72.8% faster)
130
+ pngcheck uses 5.3x less memory (81.2% less)
131
+ ----
132
+ ====
133
+
134
+ === Using Configuration Files
135
+
136
+ ==== Quick test (10 files, 2 iterations)
137
+
138
+ [source,shell]
139
+ ----
140
+ ./benchmarks/run_benchmark.rb --config config/quick.yml
141
+ ----
142
+
143
+ ==== Full test with all files and more iterations
144
+
145
+ [source,shell]
146
+ ----
147
+ ./benchmarks/run_benchmark.rb --config config/full.yml
148
+ ----
149
+
150
+ ==== Custom configuration
151
+
152
+ .Create custom configuration file
153
+ [example]
154
+ ====
155
+ [source,yaml]
156
+ ----
157
+ # my_config.yml
158
+ test_files:
159
+ pattern: "spec/fixtures/pngsuite/basic/*.png"
160
+ limit: 20
161
+
162
+ iterations: 10
163
+ warmup_runs: 3
164
+
165
+ output:
166
+ format: "json"
167
+ file: "results/my_benchmark.json"
168
+ ----
169
+
170
+ [source,shell]
171
+ ----
172
+ ./benchmarks/run_benchmark.rb --config my_config.yml
173
+ ----
174
+ ====
175
+
176
+ === Command-Line Options
177
+
178
+ ==== File Selection
179
+
180
+ `-p, --pattern PATTERN`:: File pattern to test (e.g., `spec/fixtures/**/*.png`)
181
+ `-l, --limit N`:: Limit number of files to test
182
+
183
+ .Test only 5 files from compression directory
184
+ [example]
185
+ ====
186
+ [source,shell]
187
+ ----
188
+ ./benchmarks/run_benchmark.rb \
189
+ --pattern "spec/fixtures/pngsuite/compression/*.png" \
190
+ --limit 5
191
+ ----
192
+ ====
193
+
194
+ ==== Execution Parameters
195
+
196
+ `-i, --iterations N`:: Number of iterations per file (default: 3)
197
+ `-w, --warmup N`:: Number of warmup runs (default: 1)
198
+ `-t, --tool TOOL`:: Enable specific tool only (png_conform or pngcheck)
199
+
200
+ .Run 10 iterations with 2 warmup runs
201
+ [example]
202
+ ====
203
+ [source,shell]
204
+ ----
205
+ ./benchmarks/run_benchmark.rb --iterations 10 --warmup 2
206
+ ----
207
+ ====
208
+
209
+ .Benchmark only png_conform
210
+ [example]
211
+ ====
212
+ [source,shell]
213
+ ----
214
+ ./benchmarks/run_benchmark.rb --tool png_conform
215
+ ----
216
+ ====
217
+
218
+ ==== Output Configuration
219
+
220
+ `-f, --format FORMAT`:: Output format: text, json, csv, markdown
221
+ `-o, --output FILE`:: Write report to file instead of stdout
222
+ `-q, --quiet`:: Suppress progress output
223
+
224
+ .Generate JSON report
225
+ [example]
226
+ ====
227
+ [source,shell]
228
+ ----
229
+ ./benchmarks/run_benchmark.rb \
230
+ --format json \
231
+ --output results/benchmark_$(date +%Y%m%d).json
232
+ ----
233
+ ====
234
+
235
+ .Generate CSV for spreadsheet analysis
236
+ [example]
237
+ ====
238
+ [source,shell]
239
+ ----
240
+ ./benchmarks/run_benchmark.rb \
241
+ --format csv \
242
+ --output results/benchmark.csv
243
+ ----
244
+ ====
245
+
246
+ .Generate Markdown report
247
+ [example]
248
+ ====
249
+ [source,shell]
250
+ ----
251
+ ./benchmarks/run_benchmark.rb \
252
+ --format markdown \
253
+ --output results/BENCHMARK_RESULTS.md
254
+ ----
255
+ ====
256
+
257
+ === Configuration File Format
258
+
259
+ Configuration files use YAML format:
260
+
261
+ [source,yaml]
262
+ ----
263
+ # File selection
264
+ test_files:
265
+ pattern: "spec/fixtures/pngsuite/**/*.png" # Glob pattern
266
+ exclude: [] # Patterns to exclude
267
+ limit: null # null = all files
268
+
269
+ # Execution settings
270
+ iterations: 3 # Number of benchmark runs
271
+ warmup_runs: 1 # Warmup runs (not counted)
272
+ timeout: 30 # Timeout per file (seconds)
273
+
274
+ # Tool configuration
275
+ tools:
276
+ png_conform:
277
+ enabled: true
278
+ options:
279
+ cli_options: ["--quiet"] # CLI arguments
280
+
281
+ pngcheck:
282
+ enabled: true
283
+ options:
284
+ cli_options: ["-q"]
285
+
286
+ # Output settings
287
+ output:
288
+ format: "text" # text, json, csv, markdown
289
+ file: null # null = stdout, or file path
290
+ verbose: true # Show progress
291
+ include_raw_data: false # Include raw data in JSON output
292
+ ----
293
+
294
+ == Output Formats
295
+
296
+ === Text Format
297
+
298
+ Human-readable tables with performance statistics.
299
+
300
+ .Text format example
301
+ [example]
302
+ ====
303
+ [source]
304
+ ----
305
+ ================================================================================
306
+ PNG Validation Tool Benchmark Comparison
307
+ ================================================================================
308
+
309
+ Configuration:
310
+ Files tested: 177 PNG files
311
+ Total runs: 1062
312
+
313
+ --------------------------------------------------------------------------------
314
+ PERFORMANCE SUMMARY
315
+ --------------------------------------------------------------------------------
316
+
317
+ Tool Avg Time Files/sec Peak Memory Winner
318
+ png_conform 45.2ms 22.1 45.2 MB
319
+ pngcheck 12.3ms 81.3 8.5 MB ✓
320
+
321
+ Performance Difference:
322
+ pngcheck is 3.7x faster (72.8% faster)
323
+ pngcheck uses 5.3x less memory (81.2% less)
324
+
325
+ --------------------------------------------------------------------------------
326
+ DETAILED STATISTICS
327
+ --------------------------------------------------------------------------------
328
+
329
+ png_conform:
330
+ Runs: 531/531 successful
331
+
332
+ Execution Time:
333
+ Mean: 45.2ms
334
+ Median: 43.1ms
335
+ Std Dev: 8.7ms
336
+ Min: 28.3ms
337
+ Max: 89.4ms
338
+
339
+ Memory Usage:
340
+ Mean: 45.2 MB
341
+ Median: 44.8 MB
342
+ Min: 42.1 MB
343
+ Max: 48.9 MB
344
+
345
+ Throughput:
346
+ Files/sec: 22.1
347
+ Time/file: 45.2ms
348
+
349
+ pngcheck:
350
+ [similar statistics...]
351
+ ----
352
+ ====
353
+
354
+ === JSON Format
355
+
356
+ Machine-readable structured data for CI/CD integration.
357
+
358
+ .JSON format example
359
+ [example]
360
+ ====
361
+ [source,json]
362
+ ----
363
+ {
364
+ "benchmark_info": {
365
+ "timestamp": "2025-11-18T08:00:00Z",
366
+ "files_tested": 177,
367
+ "total_runs": 1062,
368
+ "tools": ["png_conform", "pngcheck"]
369
+ },
370
+ "comparison": {
371
+ "tool1": "png_conform",
372
+ "tool2": "pngcheck",
373
+ "faster_tool": "pngcheck",
374
+ "time_difference_percent": 72.8,
375
+ "time_multiplier": 3.7,
376
+ "memory_efficient_tool": "pngcheck",
377
+ "memory_difference_percent": 81.2,
378
+ "memory_multiplier": 5.3
379
+ },
380
+ "tool_statistics": [
381
+ {
382
+ "tool": "png_conform",
383
+ "total_runs": 531,
384
+ "successful_runs": 531,
385
+ "execution_time": {
386
+ "mean": 45.2,
387
+ "median": 43.1,
388
+ "std_dev": 8.7,
389
+ "min": 28.3,
390
+ "max": 89.4
391
+ }
392
+ }
393
+ ]
394
+ }
395
+ ----
396
+ ====
397
+
398
+ === CSV Format
399
+
400
+ Spreadsheet-compatible format for data analysis.
401
+
402
+ .CSV format example
403
+ [example]
404
+ ====
405
+ [source,csv]
406
+ ----
407
+ Tool,File,Execution Time (ms),Peak Memory (MB),Success,Exit Code,Timed Out,Timestamp
408
+ png_conform,spec/fixtures/pngsuite/basic/basn0g01.png,42.3,44.5,true,0,false,2025-11-18T08:00:00Z
409
+ png_conform,spec/fixtures/pngsuite/basic/basn0g02.png,43.1,44.7,true,0,false,2025-11-18T08:00:01Z
410
+ pngcheck,spec/fixtures/pngsuite/basic/basn0g01.png,11.2,8.3,true,0,false,2025-11-18T08:00:02Z
411
+ ...
412
+ ----
413
+ ====
414
+
415
+ === Markdown Format
416
+
417
+ Documentation-friendly format for GitHub/GitLab.
418
+
419
+ .Markdown format example
420
+ [example]
421
+ ====
422
+ [source,markdown]
423
+ ----
424
+ # PNG Validation Tool Benchmark Comparison
425
+
426
+ ## Configuration
427
+
428
+ - **Files tested**: 177 PNG files
429
+ - **Total runs**: 1062
430
+ - **Tools**: png_conform, pngcheck
431
+
432
+ ## Performance Summary
433
+
434
+ | Metric | png_conform | pngcheck | Winner |
435
+ |--------|----------|----------|--------|
436
+ | Avg Time | 45.2ms | 12.3ms | pngcheck |
437
+ | Files/sec | 22.1 | 81.3 | pngcheck |
438
+ | Peak Memory | 45.2 MB | 8.5 MB | pngcheck |
439
+
440
+ **Performance:** pngcheck is 3.7x faster (72.8% improvement)
441
+
442
+ **Memory:** pngcheck uses 5.3x less memory (81.2% improvement)
443
+ ----
444
+ ====
445
+
446
+ == Interpreting Results
447
+
448
+ === Performance Metrics
449
+
450
+ Execution Time:: Time taken to validate a single PNG file (milliseconds)
451
+ Files/sec:: Throughput - how many files can be validated per second
452
+ Peak Memory:: Maximum resident set size during execution (megabytes)
453
+
454
+ === Statistical Measures
455
+
456
+ Mean:: Average value across all runs
457
+ Median:: Middle value when sorted (more robust against outliers)
458
+ Std Dev:: Standard deviation - measure of variability
459
+ Min/Max:: Minimum and maximum observed values
460
+
461
+ === Expected Results
462
+
463
+ Based on the implementation differences:
464
+
465
+ * *pngcheck* (native C): Faster execution, lower memory usage
466
+ * *png_conform* (pure Ruby): Slower execution, higher memory usage, but more features
467
+
468
+ The trade-off is between performance and functionality - png_conform provides comprehensive validation, modern chunk support, and rich reporting that pngcheck lacks.
469
+
470
+ == Troubleshooting
471
+
472
+ === pngcheck not found
473
+
474
+ .Error message
475
+ [source]
476
+ ----
477
+ Error: pngcheck is NOT available
478
+ Install with: brew install pngcheck (macOS) or apt-get install pngcheck (Linux)
479
+ ----
480
+
481
+ .Solution
482
+ [source,shell]
483
+ ----
484
+ # macOS
485
+ brew install pngcheck
486
+
487
+ # Linux (Debian/Ubuntu)
488
+ sudo apt-get install pngcheck
489
+
490
+ # Verify installation
491
+ which pngcheck
492
+ ----
493
+
494
+ === Permission denied
495
+
496
+ .Error message
497
+ [source]
498
+ ----
499
+ Permission denied: ./benchmarks/run_benchmark.rb
500
+ ----
501
+
502
+ .Solution
503
+ [source,shell]
504
+ ----
505
+ chmod +x benchmarks/run_benchmark.rb
506
+ ----
507
+
508
+ === No files found
509
+
510
+ .Error message
511
+ [source]
512
+ ----
513
+ Found 0 PNG files to test
514
+ Error: No files found matching pattern
515
+ ----
516
+
517
+ .Solution - check pattern and working directory
518
+ [source,shell]
519
+ ----
520
+ # Run from project root
521
+ cd /path/to/pngconform
522
+
523
+ # Verify files exist
524
+ ls spec/fixtures/pngsuite/**/*.png | wc -l
525
+
526
+ # Try with absolute path
527
+ ./benchmarks/run_benchmark.rb --pattern "$(pwd)/spec/fixtures/pngsuite/**/*.png"
528
+ ----
529
+
530
+ == Development
531
+
532
+ === Running Tests
533
+
534
+ To test the benchmark system itself:
535
+
536
+ [source,shell]
537
+ ----
538
+ # Quick sanity check
539
+ ./benchmarks/run_benchmark.rb --config config/quick.yml
540
+
541
+ # Verify all output formats
542
+ ./benchmarks/run_benchmark.rb --limit 5 --format text
543
+ ./benchmarks/run_benchmark.rb --limit 5 --format json
544
+ ./benchmarks/run_benchmark.rb --limit 5 --format csv
545
+ ./benchmarks/run_benchmark.rb --limit 5 --format markdown
546
+ ----
547
+
548
+ === Adding New Tools
549
+
550
+ To add a new validation tool to the benchmark:
551
+
552
+ . Create a runner class in `lib/` inheriting from [`ToolRunner`](lib/tool_runner.rb)
553
+ . Implement the `run` method
554
+ . Add configuration in [`benchmark_runner.rb`](lib/benchmark_runner.rb)
555
+ . Update configuration files
556
+
557
+ == Contributing
558
+
559
+ Improvements to the benchmark suite are welcome:
560
+
561
+ * More sophisticated statistical analysis
562
+ * Performance profiling integration
563
+ * Visualization generation
564
+ * CI/CD integration examples
565
+
566
+ == Copyright and License
567
+
568
+ Copyright Ribose.
569
+
570
+ The benchmark suite is available as open source under the Ribose BSD-2-Clause License.
@@ -0,0 +1,35 @@
1
+ # Default benchmark configuration
2
+
3
+ # Files to test
4
+ test_files:
5
+ pattern: "spec/fixtures/pngsuite/**/*.png"
6
+ exclude: []
7
+ limit: null # null = all files
8
+
9
+ # Number of benchmark iterations
10
+ iterations: 3
11
+
12
+ # Number of warmup runs (not counted in statistics)
13
+ warmup_runs: 1
14
+
15
+ # Timeout per file in seconds
16
+ timeout: 30
17
+
18
+ # Tool configuration
19
+ tools:
20
+ png_conform:
21
+ enabled: true
22
+ options:
23
+ cli_options: ["--quiet"]
24
+
25
+ pngcheck:
26
+ enabled: true
27
+ options:
28
+ cli_options: ["-q"]
29
+
30
+ # Output configuration
31
+ output:
32
+ format: "text" # Options: text, json, csv, markdown
33
+ file: null # null = stdout, or specify a file path
34
+ verbose: true
35
+ include_raw_data: false
@@ -0,0 +1,32 @@
1
+ # Full benchmark configuration - comprehensive testing
2
+
3
+ # Files to test (all files)
4
+ test_files:
5
+ pattern: "spec/fixtures/pngsuite/**/*.png"
6
+ exclude: []
7
+ limit: null # Test all files
8
+
9
+ # More iterations for statistical significance
10
+ iterations: 5
11
+ warmup_runs: 2
12
+
13
+ timeout: 30
14
+
15
+ # Tool configuration
16
+ tools:
17
+ png_conform:
18
+ enabled: true
19
+ options:
20
+ cli_options: ["--quiet"]
21
+
22
+ pngcheck:
23
+ enabled: true
24
+ options:
25
+ cli_options: ["-q"]
26
+
27
+ # Output configuration
28
+ output:
29
+ format: "text"
30
+ file: "results/full_benchmark.txt"
31
+ verbose: true
32
+ include_raw_data: true
@@ -0,0 +1,32 @@
1
+ # Quick benchmark configuration - for rapid testing
2
+
3
+ # Files to test (limited set)
4
+ test_files:
5
+ pattern: "spec/fixtures/pngsuite/**/*.png"
6
+ exclude: []
7
+ limit: 10 # Only test 10 files
8
+
9
+ # Fewer iterations for speed
10
+ iterations: 2
11
+ warmup_runs: 1
12
+
13
+ timeout: 30
14
+
15
+ # Tool configuration
16
+ tools:
17
+ png_conform:
18
+ enabled: true
19
+ options:
20
+ cli_options: ["--quiet"]
21
+
22
+ pngcheck:
23
+ enabled: true
24
+ options:
25
+ cli_options: ["-q"]
26
+
27
+ # Output configuration
28
+ output:
29
+ format: "text"
30
+ file: null
31
+ verbose: true
32
+ include_raw_data: false
@@ -0,0 +1,18 @@
1
+ #!/usr/bin/env ruby
2
+ # frozen_string_literal: true
3
+
4
+ # Measure baseline Ruby performance without CLI overhead
5
+ require_relative "../lib/png_conform"
6
+
7
+ file = ARGV[0] || "spec/fixtures/pngsuite/compression/z00n2c08.png"
8
+
9
+ start = Process.clock_gettime(Process::CLOCK_MONOTONIC)
10
+
11
+ result = PngConform::Services::ValidationService.validate_file(file,
12
+ quiet: true)
13
+
14
+ elapsed = Process.clock_gettime(Process::CLOCK_MONOTONIC) - start
15
+
16
+ puts "File: #{file}"
17
+ puts "Valid: #{result.valid?}"
18
+ puts "Time: #{(elapsed * 1000).round(1)}ms"