kit

kit
git clone https://git.ryansepassi.com/git/kit.git
Log | Files | Refs | README

o1_quality.sh (5351B)


      1 #!/usr/bin/env bash
      2 # o1_quality.sh -- A/B harness for the -O1 code-quality work (doc/plan/O1.md).
      3 #
      4 # Compiles a fixed ecosystem corpus at -O1 -c with a kit binary and reports, per
      5 # file, the __TEXT byte size and the emitted instruction count. Optionally diffs
      6 # against a baseline kit binary and/or against clang -O1.
      7 #
      8 # Usage:
      9 #   scripts/o1_quality.sh [--kit PATH] [--baseline PATH] [--clang] [--arch A]
     10 #                         [--insn-mix SYM] [name ...]
     11 #
     12 #   --kit PATH       kit binary to measure   (default: build/release/kit)
     13 #   --baseline PATH  second kit binary; report fixed-vs-baseline deltas
     14 #   --clang          also compile with clang and report kit/clang ratios
     15 #   --arch A         aa64|x64|rv64 (default aa64 -> aarch64 native on Apple Si)
     16 #   --insn-mix SYM   for the given symbol, dump the per-mnemonic count delta
     17 #   name ...         restrict to these corpus entries (default: all)
     18 #
     19 # Pitfalls (see O1.md sec.1): a kit binary copied outside build/ fails with
     20 # "support dir not found", so keep A/B binaries inside build/release/.
     21 set -euo pipefail
     22 
     23 ROOT="$(cd "$(dirname "$0")/.." && pwd)"
     24 KIT="$ROOT/build/release/kit"
     25 BASELINE=""
     26 DO_CLANG=0
     27 ARCH="aa64"
     28 INSN_MIX=""
     29 WANT=()
     30 
     31 while [ $# -gt 0 ]; do
     32   case "$1" in
     33     --kit)       KIT="$2"; shift 2 ;;
     34     --baseline)  BASELINE="$2"; shift 2 ;;
     35     --clang)     DO_CLANG=1; shift ;;
     36     --arch)      ARCH="$2"; shift 2 ;;
     37     --insn-mix)  INSN_MIX="$2"; shift 2 ;;
     38     -h|--help)   sed -n '2,22p' "$0"; exit 0 ;;
     39     *)           WANT+=("$1"); shift ;;
     40   esac
     41 done
     42 
     43 case "$ARCH" in
     44   aa64) KTARGET="aarch64-macos"; CTARGET="arm64-apple-macos" ;;
     45   x64)  KTARGET="x86_64-macos";  CTARGET="x86_64-apple-macos" ;;
     46   rv64) KTARGET="riscv64-linux-gnu"; CTARGET="" ;;
     47   *) echo "unknown --arch $ARCH" >&2; exit 1 ;;
     48 esac
     49 
     50 SDK="$(xcrun --sdk macosx --show-sdk-path 2>/dev/null || true)"
     51 WORK="$ROOT/build/o1_quality"
     52 mkdir -p "$WORK"
     53 
     54 # corpus: name | relpath-under-srcdir | extra-cflags (use @SRC@ for -I srcdir)
     55 corpus() {
     56   cat <<EOF
     57 lapi|lua|lapi.c|-I@SRC@
     58 lparser|lua|lparser.c|-I@SRC@
     59 lvm|lua|lvm.c|-I@SRC@
     60 sqlite|sqlite|sqlite3.c|
     61 cjson|cjson|cJSON.c|-I@SRC@
     62 lz4|lz4|lz4.c|-I@SRC@
     63 miniz|miniz|miniz.c|
     64 yyjson|yyjson|yyjson.c|-I@SRC@
     65 tinyexpr|tinyexpr|tinyexpr.c|-I@SRC@
     66 EOF
     67 }
     68 
     69 text_bytes() { # $1=objfile -> __text byte count (Mach-O), 0 if absent
     70   size -m "$1" 2>/dev/null | awk '/__text/{print $NF; found=1} END{if(!found)print 0}'
     71 }
     72 insn_count() { # $1=objfile -> emitted instruction count
     73   "$KIT" objdump -d "$1" 2>/dev/null | awk '/^[[:space:]]*[0-9a-f]+:\t/{n++} END{print n+0}'
     74 }
     75 
     76 compile_kit() { # $1=kitbin $2=src $3=out $4=extra
     77   "$1" cc -O1 -std=c11 -target "$KTARGET" --sysroot "$SDK" $4 -c "$2" -o "$3" 2>>"$WORK/err.log"
     78 }
     79 compile_clang() { # $1=src $2=out $3=extra
     80   clang -O1 -std=c11 -target "$CTARGET" -isysroot "$SDK" $3 -c "$1" -o "$2" 2>>"$WORK/err.log"
     81 }
     82 
     83 printf '%-10s %12s %10s' "file" "kit_text" "kit_insn"
     84 [ -n "$BASELINE" ] && printf ' %12s %8s' "base_text" "dTEXT%"
     85 [ "$DO_CLANG" = 1 ] && printf ' %11s %8s' "clang_text" "k/clang"
     86 printf '\n'
     87 
     88 : > "$WORK/err.log"
     89 tot_k=0; tot_b=0; tot_c=0
     90 while IFS='|' read -r name eco rel extra; do
     91   [ -n "$name" ] || continue
     92   if [ "${#WANT[@]}" -gt 0 ]; then
     93     skip=1; for w in "${WANT[@]}"; do [ "$w" = "$name" ] && skip=0; done
     94     [ "$skip" = 1 ] && continue
     95   fi
     96   src_root="$("$ROOT/scripts/ecosystem.sh" srcdir "$eco" 2>/dev/null || true)"
     97   [ -n "$src_root" ] || { printf '%-10s  (not provisioned)\n' "$name"; continue; }
     98   src="$src_root/$rel"
     99   [ -f "$src" ] || { printf '%-10s  (missing %s)\n' "$name" "$rel"; continue; }
    100   ex="${extra//@SRC@/$src_root}"
    101 
    102   ko="$WORK/$name.k.o"
    103   compile_kit "$KIT" "$src" "$ko" "$ex" || { printf '%-10s  (kit FAILED)\n' "$name"; continue; }
    104   kt="$(text_bytes "$ko")"; ki="$(insn_count "$ko")"
    105   tot_k=$((tot_k + kt))
    106   printf '%-10s %12s %10s' "$name" "$kt" "$ki"
    107 
    108   if [ -n "$BASELINE" ]; then
    109     bo="$WORK/$name.b.o"
    110     if compile_kit "$BASELINE" "$src" "$bo" "$ex"; then
    111       bt="$(text_bytes "$bo")"; tot_b=$((tot_b + bt))
    112       d="n/a"; [ "$bt" -gt 0 ] && d="$(awk -v k="$kt" -v b="$bt" 'BEGIN{printf "%+.2f", (k-b)*100.0/b}')"
    113       printf ' %12s %8s' "$bt" "$d"
    114     else
    115       printf ' %12s %8s' "FAIL" "-"
    116     fi
    117   fi
    118   if [ "$DO_CLANG" = 1 ] && [ -n "$CTARGET" ]; then
    119     co="$WORK/$name.c.o"
    120     if compile_clang "$src" "$co" "$ex"; then
    121       ct="$(text_bytes "$co")"; tot_c=$((tot_c + ct))
    122       r="n/a"; [ "$ct" -gt 0 ] && r="$(awk -v k="$kt" -v c="$ct" 'BEGIN{printf "%.2f", k*1.0/c}')"
    123       printf ' %11s %8s' "$ct" "$r"
    124     else
    125       printf ' %11s %8s' "FAIL" "-"
    126     fi
    127   fi
    128   printf '\n'
    129 
    130   if [ -n "$INSN_MIX" ]; then
    131     "$KIT" objdump -d "$ko" 2>/dev/null | awk -v want="$INSN_MIX" '
    132       $0 ~ ("<" want ">:") {inf=1; next} /^[0-9a-f]+ </{inf=0}
    133       inf && /^[[:space:]]*[0-9a-f]+:\t/ {n=split($0,a,"\t"); split(a[3],m," "); c[m[1]]++}
    134       END{for(k in c) printf "    %-10s %d\n", k, c[k]}' | sort -k2 -rn | head -25
    135   fi
    136 done < <(corpus)
    137 
    138 printf '%-10s %12s\n' "TOTAL" "$tot_k"
    139 [ -n "$BASELINE" ] && [ "$tot_b" -gt 0 ] && \
    140   awk -v k="$tot_k" -v b="$tot_b" 'BEGIN{printf "  fixed vs baseline __TEXT: %+.2f%%\n", (k-b)*100.0/b}'
    141 [ "$DO_CLANG" = 1 ] && [ "$tot_c" -gt 0 ] && \
    142   awk -v k="$tot_k" -v c="$tot_c" 'BEGIN{printf "  kit/clang aggregate __TEXT: %.3fx\n", k*1.0/c}'
    143 echo "  (errors, if any, in $WORK/err.log)"