Files
obikmer/benchmark/pack_sparse.sh
T

87 lines
2.7 KiB
Bash
Raw Normal View History

#!/usr/bin/env bash
# Builds global_index_presence_sparse/ from global_index_presence/ by
# copying the index (column files are kept in place after merge's dense
# pack — see obikindex::KmerIndex::pack_matrices) and repacking in place
# with --sparse.
# Outputs:
# global_index_presence_sparse/index.done (copied from source)
# stats/pack_sparse/current.stats (one CSV data row, no header)
set -euo pipefail
SCRIPT_DIR="$(cd "$(dirname "${BASH_SOURCE[0]}")" && pwd)"
BINARY="${SCRIPT_DIR}/../src/target/release/obikmer"
SOURCE="${SCRIPT_DIR}/global_index_presence"
OUTPUT="${SCRIPT_DIR}/global_index_presence_sparse"
STATS_DIR="${SCRIPT_DIR}/stats/pack_sparse"
STATS_FILE="${STATS_DIR}/current.stats"
mkdir -p "${STATS_DIR}"
echo "[pack_sparse] ${SOURCE}${OUTPUT}"
rm -rf "${OUTPUT}"
cp -r "${SOURCE}" "${OUTPUT}"
STDERR_LOG=$(mktemp)
trap 'rm -f "${STDERR_LOG}"' EXIT
"${BINARY}" pack --sparse "${OUTPUT}" 2>"${STDERR_LOG}"
cat "${STDERR_LOG}" >&2
python3 - "${STDERR_LOG}" <<'PYEOF' >"${STATS_FILE}"
import sys, re
logfile = sys.argv[1]
def strip_ansi(s):
return re.sub(r'\x1b\[[\x30-\x3f]*[\x20-\x2f]*[\x40-\x7e]', '', s)
def parse_wall(s):
s = s.strip()
if s.endswith('ms'): return float(s[:-2]) / 1000.0
if s.endswith('s'): return float(s[:-1])
return 0.0
def parse_rss(s):
m = re.match(r'([\d.]+)\s*(GB|MB|KB|B)', s.strip())
if not m: return 0
return int(float(m.group(1)) * {'GB': 1<<30, 'MB': 1<<20, 'KB': 1024, 'B': 1}[m.group(2)])
def is_sep(s):
return bool(s) and not re.search(r'[A-Za-z0-9]', s)
stats = {}
state = 'scan'
with open(logfile, errors='replace') as fh:
for raw in fh:
line = strip_ansi(raw.rstrip('\n'))
s = line.strip()
if state == 'scan':
if re.search(r'\bstage\b.*\bwall\b', line):
state = 'in_header'
elif state == 'in_header':
if is_sep(s): state = 'rows'
elif state == 'rows':
if is_sep(s): state = 'total'
elif s:
parts = re.split(r' +', s)
if len(parts) >= 4:
stats[parts[0]] = (parse_wall(parts[1]), parse_rss(parts[3]))
elif state == 'total':
if s:
parts = re.split(r' +', s)
if len(parts) >= 3:
stats['TOTAL'] = (parse_wall(parts[1]),
parse_rss(parts[3]) if len(parts) > 3 else 0)
break
w, r = stats.get('pack', ('', ''))
tw, tr = stats.get('TOTAL', ('', ''))
row = [f'{w:.3f}' if isinstance(w, float) else '', str(r),
f'{tw:.3f}' if isinstance(tw, float) else '', str(tr)]
print(','.join(row))
PYEOF
echo "Done → ${OUTPUT}"