@@ -10,6 +10,39 @@ BIDIFF="$ROOT/target/release/bidiff"
1010
1111mkdir -p " $DATA "
1212
13+ # Portable sha256 (Linux has sha256sum, macOS has shasum)
14+ sha256 () {
15+ if command -v sha256sum > /dev/null 2>&1 ; then
16+ sha256sum " $1 " | cut -d' ' -f1
17+ else
18+ shasum -a 256 " $1 " | cut -d' ' -f1
19+ fi
20+ }
21+
22+ # ── System info ──────────────────────────────────────────────────────────────
23+
24+ system_info () {
25+ local cpu cores ram_gib os_name
26+ case " $( uname -s) " in
27+ Darwin)
28+ cpu=$( sysctl -n machdep.cpu.brand_string 2> /dev/null)
29+ cores=$( sysctl -n hw.ncpu 2> /dev/null)
30+ ram_gib=$( sysctl -n hw.memsize 2> /dev/null | awk ' {printf "%g", $1 / 1073741824}' )
31+ os_name=" $( sw_vers -productName) $( sw_vers -productVersion) "
32+ ;;
33+ Linux)
34+ cpu=$( grep -m1 ' model name' /proc/cpuinfo | sed ' s/.*: //' )
35+ cores=$( nproc)
36+ ram_gib=$( awk ' /MemTotal/ {printf "%g", $2 / 1048576}' /proc/meminfo)
37+ os_name=" Linux $( uname -r | cut -d- -f1) "
38+ ;;
39+ * )
40+ cpu=" unknown" ; cores=" ?" ; ram_gib=" ?" ; os_name=" $( uname -s) "
41+ ;;
42+ esac
43+ echo " System: ${cpu} (${cores} cores), ${ram_gib} GiB RAM, ${os_name} ."
44+ }
45+
1346# ── Download helpers ─────────────────────────────────────────────────────────
1447
1548download () {
@@ -21,7 +54,7 @@ download() {
2154 echo " downloading: $( basename " $dest " ) "
2255 curl -fSL --progress-bar -o " $dest " " $url "
2356 local actual
24- actual=$( sha256sum " $dest " | cut -d ' ' -f1 )
57+ actual=$( sha256 " $dest " )
2558 if [ " $actual " != " $sha256 " ]; then
2659 echo " ERROR: checksum mismatch for $dest "
2760 echo " expected: $sha256 "
@@ -88,9 +121,11 @@ extract_chrome() {
88121 return
89122 fi
90123 echo " extracting: $( basename " $dest " ) from $( basename " $deb " ) "
91- dpkg-deb --fsys-tarfile " $deb " | tar xf - --to-stdout ./opt/google/chrome/chrome > " $dest "
124+ local data_tar
125+ data_tar=$( ar t " $deb " | grep ' ^data\.tar' )
126+ ar p " $deb " " $data_tar " | tar xf - -O ./opt/google/chrome/chrome > " $dest "
92127 local actual
93- actual=$( sha256sum " $dest " | cut -d ' ' -f1 )
128+ actual=$( sha256 " $dest " )
94129 if [ " $actual " != " $sha256 " ]; then
95130 echo " ERROR: checksum mismatch for $dest "
96131 echo " expected: $sha256 "
@@ -157,12 +192,12 @@ add_pair "Chrome 78.0.3904.97 → 108" "$DATA/chrome-78.0.3904.97" "$DATA/chrome
157192parse_cycle () {
158193 local line=" $1 "
159194 # Extract fields by keyword
160- PATCH_SIZE=$( echo " $line " | grep -oP ' patch \K [0-9.]+ [A-Za-z]+' )
161- RATIO=$( echo " $line " | grep -oP ' [0-9.]+(?= % of) ' )
162- NEW_SIZE=$( echo " $line " | grep -oP ' % of \K [0-9.]+ [A-Za-z]+' )
163- DTIME_RAW=$( echo " $line " | grep -oP ' dtime \K[0-9.]+[a-zµ]+ ' )
164- PTIME_RAW=$( echo " $line " | grep -oP ' ptime \K[0-9.]+[a-zµ]+ ' )
165- ANON=$( echo " $line " | grep -oP ' anon \K [0-9.]+ [A-Za-z]+' || echo " " )
195+ PATCH_SIZE=$( echo " $line " | grep -oE ' patch [0-9.]+ [A-Za-z]+' | sed ' s/^patch // ' )
196+ RATIO=$( echo " $line " | grep -oE ' [0-9.]+% of' | sed ' s/% of// ' )
197+ NEW_SIZE=$( echo " $line " | grep -oE ' % of [0-9.]+ [A-Za-z]+' | sed ' s/^% of // ' )
198+ DTIME_RAW=$( echo " $line " | grep -oE ' dtime [^ ]+ ' | sed ' s/^dtime // ' )
199+ PTIME_RAW=$( echo " $line " | grep -oE ' ptime [^ ]+ ' | sed ' s/^ptime // ' )
200+ ANON=$( echo " $line " | grep -oE ' anon [0-9.]+ [A-Za-z]+' | sed ' s/^anon // ' || echo " " )
166201}
167202
168203# Convert Rust Duration debug format to seconds
@@ -179,6 +214,16 @@ to_seconds() {
179214 fi
180215}
181216
217+ # Average a list of numeric values (passed as arguments)
218+ average () {
219+ local sum=0 n=0
220+ for v in " $@ " ; do
221+ sum=$( awk " BEGIN {printf \" %.6f\" , $sum + $v }" )
222+ n=$(( n + 1 ))
223+ done
224+ awk " BEGIN {printf \" %.3f\" , $sum / $n }"
225+ }
226+
182227# Format seconds for display: seconds if <60, Xm Ys if >=60
183228fmt_time () {
184229 local secs=" $1 "
@@ -208,6 +253,15 @@ declare -a R_MEM=()
208253declare -a R_DTIME_RAM=()
209254declare -a R_MEM_RAM=()
210255
256+ RUNS=5
257+
258+ # On macOS, run one extra warmup iteration (discarded) to avoid prefetch distortion
259+ if [ " $( uname -s) " = " Darwin" ]; then
260+ WARMUP=1
261+ else
262+ WARMUP=0
263+ fi
264+
211265for i in " ${! NAMES[@]} " ; do
212266 name=" ${NAMES[$i]} "
213267 older=" ${OLDERS[$i]} "
@@ -216,53 +270,73 @@ for i in "${!NAMES[@]}"; do
216270 echo " "
217271 echo " --- $name ---"
218272
219- # Default mode (file-backed hash table)
220- echo " file-backed + anon measurement..."
221- output=$( " $BIDIFF " cycle " $older " " $newer " --with-anon 2> /dev/null)
222- echo " $output "
223- parse_cycle " $output "
273+ # Timing runs: 5x each, no --with-anon so numbers aren't contaminated
274+ declare -a dtimes=() ptimes=() dtimes_ram=()
275+
276+ TOTAL=$(( WARMUP + RUNS))
277+ echo " file-backed (timing, ${RUNS} runs)..."
278+ for r in $( seq 1 $TOTAL ) ; do
279+ output=$( " $BIDIFF " cycle " $older " " $newer " 2> /dev/null)
280+ if [ " $r " -le " $WARMUP " ]; then
281+ echo " warmup: $output "
282+ continue
283+ fi
284+ actual=$(( r - WARMUP))
285+ echo " run $actual /$RUNS : $output "
286+ parse_cycle " $output "
287+ dtimes+=(" $( to_seconds " $DTIME_RAW " ) " )
288+ ptimes+=(" $( to_seconds " $PTIME_RAW " ) " )
289+ done
224290
225291 R_NAME+=(" $name " )
226292 R_NEW_SIZE+=(" $NEW_SIZE " )
227293 R_PATCH_SIZE+=(" $PATCH_SIZE " )
228294 R_RATIO+=(" $RATIO " )
229- R_PTIME+=(" $( to_seconds " $PTIME_RAW " ) " )
230- R_DTIME+=(" $( to_seconds " $DTIME_RAW " ) " )
295+ R_DTIME+=(" $( average " ${dtimes[@]} " ) " )
296+ R_PTIME+=(" $( average " ${ptimes[@]} " ) " )
297+
298+ echo " RAM (timing, ${RUNS} runs)..."
299+ for r in $( seq 1 $TOTAL ) ; do
300+ output=$( " $BIDIFF " cycle " $older " " $newer " --ram 2> /dev/null)
301+ if [ " $r " -le " $WARMUP " ]; then
302+ echo " warmup: $output "
303+ continue
304+ fi
305+ actual=$(( r - WARMUP))
306+ echo " run $actual /$RUNS : $output "
307+ parse_cycle " $output "
308+ dtimes_ram+=(" $( to_seconds " $DTIME_RAW " ) " )
309+ done
310+
311+ R_DTIME_RAM+=(" $( average " ${dtimes_ram[@]} " ) " )
312+
313+ unset dtimes ptimes dtimes_ram
314+
315+ # Memory measurement runs (single run each, separate from timing)
316+ echo " file-backed (memory)..."
317+ output=$( " $BIDIFF " cycle " $older " " $newer " --with-anon 2> /dev/null)
318+ echo " $output "
319+ parse_cycle " $output "
231320 R_MEM+=(" $ANON " )
232321
233- # RAM mode
234- echo " RAM mode + anon measurement..."
322+ echo " RAM (memory)..."
235323 output=$( " $BIDIFF " cycle " $older " " $newer " --ram --with-anon 2> /dev/null)
236324 echo " $output "
237325 parse_cycle " $output "
238-
239- R_DTIME_RAM+=(" $( to_seconds " $DTIME_RAW " ) " )
240326 R_MEM_RAM+=(" $ANON " )
241327done
242328
243329# ── Print summary table ─────────────────────────────────────────────────────
244330
245331echo " "
246332echo " "
247- echo " === Results ==="
333+ system_info
334+ echo " "
335+ echo " Default settings (1 MiB chunks, file-backed hash table). Memory column shows peak anonymous RSS during diffing."
248336echo " "
249- printf " | %-28s | %8s | %12s | %6s | %10s | %10s | %10s | %15s | %12s |\n" \
250- " Test case" " New size" " Patch size" " Ratio" " Patch time" " Diff time" " Memory" " Diff time (RAM)" " Memory (RAM)"
251- printf " |%-30s|%10s|%14s|%8s|%12s|%12s|%12s|%17s|%14s|\n" \
252- " ------------------------------" " ----------" " --------------" " --------" " ------------" " ------------" " ------------" " -----------------" " --------------"
337+ echo " | Test case | New size | Patch size | Ratio | Patch time | Diff time | Memory | Diff time (RAM) | Memory (RAM) |"
338+ echo " |-----------|----------|------------|-------|------------|-----------|--------|-----------------|--------------|"
253339
254340for i in " ${! R_NAME[@]} " ; do
255- printf " | %-28s | %8s | %12s | %5s%% | %10s | %10s | %10s | %15s | %12s |\n" \
256- " ${R_NAME[$i]} " \
257- " ${R_NEW_SIZE[$i]} " \
258- " ${R_PATCH_SIZE[$i]} " \
259- " ${R_RATIO[$i]} " \
260- " $( fmt_time " ${R_PTIME[$i]} " ) " \
261- " $( fmt_time " ${R_DTIME[$i]} " ) " \
262- " ${R_MEM[$i]} " \
263- " $( fmt_time " ${R_DTIME_RAM[$i]} " ) " \
264- " ${R_MEM_RAM[$i]} "
341+ echo " | ${R_NAME[$i]} | ${R_NEW_SIZE[$i]} | ${R_PATCH_SIZE[$i]} | ${R_RATIO[$i]} % | $( fmt_time " ${R_PTIME[$i]} " ) | $( fmt_time " ${R_DTIME[$i]} " ) | ${R_MEM[$i]} | $( fmt_time " ${R_DTIME_RAM[$i]} " ) | ${R_MEM_RAM[$i]} |"
265342done
266-
267- echo " "
268- echo " Done."
0 commit comments