|
| 1 | +#!/bin/bash |
| 2 | +# Benchmark: Compare old vs new dd skip implementation |
| 3 | +# |
| 4 | +# OLD: Uses io::copy + BufReader (internal 8KB chunks regardless of ibs) |
| 5 | +# NEW: Uses direct read loop with ibs-sized buffer (matches GNU dd) |
| 6 | + |
| 7 | +set -e |
| 8 | + |
| 9 | +GNU_DD="/bin/dd" |
| 10 | +OLD_DD="/tmp/dd_old" |
| 11 | +NEW_DD="/tmp/dd_new" |
| 12 | + |
| 13 | +echo "==============================================" |
| 14 | +echo "DD Skip Buffer Implementation Comparison" |
| 15 | +echo "==============================================" |
| 16 | +echo "" |
| 17 | +echo "Comparing three implementations:" |
| 18 | +echo " GNU dd: Reference implementation" |
| 19 | +echo " OLD: io::copy + BufReader (before this PR)" |
| 20 | +echo " NEW: Direct read with ibs-sized buffer (this PR)" |
| 21 | +echo "" |
| 22 | + |
| 23 | +count_stdin_reads() { |
| 24 | + local dd_cmd="$1" |
| 25 | + local ibs="$2" |
| 26 | + local skip_bytes=$((10 * 1024 * 1024)) # 10MB |
| 27 | + local skip_blocks=$((skip_bytes / ibs)) |
| 28 | + cat /dev/zero | strace -e read "$dd_cmd" ibs=$ibs skip=$skip_blocks count=1 of=/dev/null 2>&1 | grep -c "^read(0" |
| 29 | +} |
| 30 | + |
| 31 | +show_read_request() { |
| 32 | + local dd_cmd="$1" |
| 33 | + local ibs="$2" |
| 34 | + local skip_bytes=$((1 * 1024 * 1024)) # 1MB |
| 35 | + local skip_blocks=$((skip_bytes / ibs)) |
| 36 | + # Show the size requested in the read() call |
| 37 | + cat /dev/zero | strace -e read "$dd_cmd" ibs=$ibs skip=$skip_blocks count=1 of=/dev/null 2>&1 | grep "^read(0" | head -1 | sed 's/.*,\s*\([0-9]*\)).*/\1/' |
| 38 | +} |
| 39 | + |
| 40 | +echo "==============================================" |
| 41 | +echo "Test 1: Read Request Size (what size buffer is used)" |
| 42 | +echo "==============================================" |
| 43 | +echo "" |
| 44 | +echo "This shows the 3rd argument to read() - the buffer size requested." |
| 45 | +echo "GNU dd uses ibs. OLD used fixed size. NEW should match GNU." |
| 46 | +echo "" |
| 47 | + |
| 48 | +printf "%-12s %-15s %-15s %-15s\n" "ibs" "GNU dd" "OLD (before)" "NEW (after)" |
| 49 | +printf "%-12s %-15s %-15s %-15s\n" "---" "------" "-----------" "----------" |
| 50 | + |
| 51 | +for ibs in 512 8192 1048576; do |
| 52 | + gnu_size=$(show_read_request "$GNU_DD" "$ibs") |
| 53 | + old_size=$(show_read_request "$OLD_DD" "$ibs") |
| 54 | + new_size=$(show_read_request "$NEW_DD" "$ibs") |
| 55 | + printf "%-12s %-15s %-15s %-15s\n" "$ibs" "$gnu_size" "$old_size" "$new_size" |
| 56 | +done |
| 57 | + |
| 58 | +echo "" |
| 59 | +echo "==============================================" |
| 60 | +echo "Test 2: Syscall Count (skipping 10MB)" |
| 61 | +echo "==============================================" |
| 62 | +echo "" |
| 63 | +echo "Fewer syscalls = more efficient (for large ibs)." |
| 64 | +echo "More syscalls = correct behavior (for small ibs)." |
| 65 | +echo "" |
| 66 | + |
| 67 | +printf "%-12s %-10s %-12s %-15s %-15s\n" "ibs" "Expected" "GNU dd" "OLD (before)" "NEW (after)" |
| 68 | +printf "%-12s %-10s %-12s %-15s %-15s\n" "---" "--------" "------" "-----------" "----------" |
| 69 | + |
| 70 | +for ibs in 512 8192 65536; do |
| 71 | + expected=$((10 * 1024 * 1024 / ibs)) |
| 72 | + gnu_count=$(count_stdin_reads "$GNU_DD" "$ibs") |
| 73 | + old_count=$(count_stdin_reads "$OLD_DD" "$ibs") |
| 74 | + new_count=$(count_stdin_reads "$NEW_DD" "$ibs") |
| 75 | + printf "%-12s %-10s %-12s %-15s %-15s\n" "$ibs" "~$expected" "$gnu_count" "$old_count" "$new_count" |
| 76 | +done |
| 77 | + |
| 78 | +echo "" |
| 79 | +echo "==============================================" |
| 80 | +echo "Analysis" |
| 81 | +echo "==============================================" |
| 82 | +echo "" |
| 83 | +echo "OLD behavior (io::copy + BufReader):" |
| 84 | +echo " - Always used ~8KB internal buffer regardless of ibs" |
| 85 | +echo " - ~1,280 syscalls for 10MB regardless of ibs setting" |
| 86 | +echo " - Did NOT match GNU dd behavior" |
| 87 | +echo "" |
| 88 | +echo "NEW behavior (direct read with ibs buffer):" |
| 89 | +echo " - Uses ibs-sized buffer as specified by user" |
| 90 | +echo " - Syscall count scales with ibs (matches GNU dd)" |
| 91 | +echo " - Correctly implements dd semantics" |
0 commit comments