Skip to content

v0.8.0

Latest

Choose a tag to compare

@github-actions github-actions released this 03 Aug 22:49
c11092b

0.8.0 — a verified drop-in for bwa-mem2, ~13% faster, and corrected methylation tags

1. --compat=bwa-mem2 — swap in bwa-mem3 and get the same BAM

The big one. Run bwa-mem3 mem --compat=bwa-mem2 ... and you get the same alignments bwa-mem2 v2.2.1 would have produced — same positions, same CIGARs, same MAPQs, same flags, same tags, same header.

We verified this rather than asserting it. Across 7 datasets (WGS, WES, targeted panel, Hi-C, single-end, and two simulated sets) on 6 CPU types (Intel and AMD x86, plus ARM/Graviton), repeated 5 times each — 210 alignment runs totalling 1.57 billion alignment records — every record matched, field for field. Zero differences.

That includes ARM. If you have been running bwa-mem2 on x86 and want to move to Graviton, this is the first release where we can show the output is the same.

Why you'd use it: drop bwa-mem3 into an existing validated pipeline without revalidating. You give up some of the speed below (the compat path matches bwa-mem2's exact search behaviour), but you get the newer codebase, active maintenance, and ARM support with no change to your results.

2. Faster — about 13% off the default path, 18% with --fast

Median wall-clock improvement versus 0.7.0, measured on the same hardware:

median speedup best on a real dataset
default path −13% −25% (Hi-C, Graviton4)
--fast −18% −28% (WGS, Graviton4)

Across 79 timed comparisons against 0.7.0: 45 got faster, 12 were unchanged, 22 were too noisy to call, and 0 got slower. Gains are largest on ARM (Graviton3 −17%, Graviton4 −14%) and solid on AMD (−8 to −9%).

Multi-threaded scaling also improved — at 64 threads, efficiency is up 3.7 points, so large -t values waste less of the machine.

3. Methylation — corrected tags, and one breaking change

Warning

--meth now writes SAM text, not BAM. Add --bam if you were relying on binary output. If you already pipe into samtools, nothing changes — it autodetects.

Two real correctness fixes for bisulfite/EM-seq data:

  • NM and MD are now correct. They previously counted C→T and G→A conversions as mismatches, inflating the apparent edit distance on nearly every read. They are now derived from the scoring matrix.
  • MQ and HN are now emitted under --meth; they were silently missing.

This changes your output. NM, MD, and XA values differ on ~99% of reads versus 0.7.0 — but that is the tag values being fixed, not reads moving. Placement is essentially unchanged: of 20,742 reads, 7 moved. If you filter or QC on NM, expect different (correct) numbers.

Also new: --meth-tags to choose which Bismark-style tags are emitted.

Should I upgrade?

  • Using --meth? Read the breaking note, and expect corrected NM/MD. Worth it.
  • Standard DNA alignment? Faster, with a small bounded change to results — 99.82–99.99% of reads place identically to 0.7.0, from improved mate rescue. Consistent across every CPU type, so it's an algorithm change, not a platform quirk.
  • Need bit-for-bit reproducibility with bwa-mem2? Use --compat=bwa-mem2.

One reproducibility note worth knowing: bwa-mem2 (and bwa) produce slightly different output at different -t values, because insert-size statistics are estimated per batch and batch size scales with thread count. Under --compat we pin the batch, so thread count no longer affects your results — verified identical at -t 16 and -t 32.

Benchmarked on the bwa-mem3-bench suite: six architectures, five replicates. Equivalence to bwa-mem2 is checked with fgumi compare bams, which compares all eleven SAM fields plus every tag value and the header.


0.8.0 (2026-08-03)

⚠ BREAKING CHANGES

  • meth: bwa-mem3 mem --meth now writes SAM text instead of BAM. Add --bam to any script that depended on the old behavior. Pipelines that pipe into samtools need no change — samtools autodetects SAM text.

Features

  • bam: warn that in-process compressed BAM is single-threaded (#287) (9cd414d)
  • mem: --compat target enum with record + header byte-identity to bwa-mem2 (#277) (265b427)
  • mem: band mate rescue to a k-mer anchor diagonal (--rescue-kmer) (#335) (6ce2b70)
  • meth: add --meth-tags to select which Bismark tags are emitted (#333) (3ec4500), closes #331
  • meth: let --bam choose the output container under --meth (#341) (ed4400c)

Bug Fixes

  • bntseq: don't poison the pac-fetch buffer in release builds (#263) (1252f1b)
  • bsw: compute the 8-bit band clamp in wide arithmetic (#270) (00ade6d)
  • bsw: correct 8-bit banded-SW z-drop and seed clamp at high seed scores (all tiers) (#273) (e722ed0)
  • build: generate header dependencies instead of a hand-maintained list (#299) (414ac7e)
  • chain: keep sizeof(mem_chain_t) at 48 B to preserve bwa-mem2 chaining parity (#268) (a9d9445)
  • check debug_macro_flag_lint's directory argument before cd (#352) (14d8096)
  • coderabbit: list main in auto_review.base_branches (#358) (63add93)
  • header: emit one default @HD on every output path (#291) (56889e1), closes #288
  • index: cap each pread() at 1GiB so large indexes load on macOS (#259) (1db6697)
  • index: resolve the auto memory budget from the host, not a 32 GiB cap (#300) (a8ac368)
  • kswv: zero query padding in the NEON and AVX-512BW 8-bit mate-rescue kernels (#290) (b8d5aa3)
  • mem: guard allocations with xassert so OOM checks survive NDEBUG (#312) (8898782)
  • mem: make the batch-size cap opt-in so default batching matches bwa-mem2 (#298) (5a85305)
  • meth: derive NM/MD from the scoring matrix so conversions are not counted (#332) (6aa4675), closes #327
  • meth: diagnose orphaned --meth/--meth-tags values instead of aligning to them (#334) (a18b19b), closes #331
  • meth: emit MQ:i and HN:i from the --meth BAM writer (#304) (70d1270), closes #296
  • meth: reject mate rescues whose SW alignment runs past the read (#258) (6ecc61b)
  • sam: make the SAM-A9 rid check opt-in so the recompute is skipped (#330) (87f3bd6)
  • simd: map _MM_HINT_T0 to L1, not L3, on arm64 (#262) (34cb389)

Performance

  • bntseq: O(1) contig bucket table for bns_pos2rid (#275) (e0291ec)
  • bntseq: unpack the 2-bit reference with a byte->4-base LUT (#274) (a9b570f)
  • bsw: admit high-h0 pairs to the 8-bit banded-SW tier (#321) (35f3238)
  • bsw: drop a redundant compare in the 8-bit row argmax (#266) (ed34d5d)
  • bsw: fuse the SBT pre-pass into the 8-bit DP loop with two LUTs (#280) (94cbdf2)
  • bsw: pack the int8 lane groups by max(len1,len2) (#283) (7898254)
  • chain: hoist chain bounds and memoize the per-chain log() (#265) (7703634)
  • chain: skip side-effect-free comparisons in mem_chain_flt (#326) (6ca3c7e)
  • io: pool per-read string fields in a per-chunk arena (#293) (c63eba0)
  • kswv: recover the query end after the row, via block checkpoints (#328) (f099e79)
  • kswv: stop testing for query padding on columns that cannot have any (#324) (90be8df)
  • main: calibrate proc_freq without sleeping a full second (#295) (052a84a)
  • mem: fuse the seed and extend kt_for passes (#264) (d4127e9)
  • mem: read a pestat cohort in slices so compute starts sooner (#305) (212ed34)
  • mem: reserve the cohort accumulator from task_size instead of doubling (#342) (80e40ad)
  • mem: size chaining scratch per thread instead of per read (#297) (3d66be4)
  • mem: size the cohort ramp so it cannot outrun the reader (#315) (160adae)
  • mem: size the per-chunk read pool from the actual read count (#279) (3848339)
  • meth: share the generic writer's per-record scratch with the meth writer (#306) (8fade15)
  • rescue: drop redundant mate-query copies in batched mate-SW (#284) (32f17e5)
  • rescue: single-position anchor index, plus an opt-in --rescue-skip gate (#349) (e7e00af)
  • sam,seed: micro-cleanups in SAM formatting and seeding (#286) (82257ab)
  • seed: correct the FM-index checkpoint prefetch targets (#267) (6455cad)
  • seed: reuse sortSMEMs counting-sort scratch across batches (#278) (394f8f8)
  • sort: move the pdqsort/total-order dedup sort behind --fast (#257) (34b3446)
  • sort: run pdqsort in the dedup sorts when the comparator sees no tie (#261) (7481c4f)

Refactoring

  • bsw: derive extension gaps from M again (bwa-mem2 compatibility) (#256) (771376e)
  • bsw: drop the unreachable 8-bit re-baselining in the AVX2/AVX-512 kernels (#272) (f1a0da6)
  • bsw: drop the unreachable 8-bit score re-baselining (#271) (ecebf2b)
  • chain: fuse mem_chain_weight's two seed sweeps into one (#322) (500c9cb)
  • chain: remove dead work from the chaining path (#285) (8de7e5b)
  • chain: tidy mem_chain_flt's filter loops (#323) (095b401)
  • header: one generated-@SQ builder, one scanner, one record iterator (#292) (37e5e4a)
  • meth: name the native-regen decision and document the hypothesis invariant (#337) (97eb3be)

Documentation

  • correct the developer guide's account of the source-only lints (#354) (a8825f5)
  • equivalence: reflect restored bwa-mem2 byte-identity on the drop-in profile (#276) (8dbf218)
  • kswv: the phase-1 boundary-mask cost is measured now, not unmeasurable (#308) (136cc9f)
  • memory: measure the -t batch multiplier cost and correct the resident index figure (#319) (804f20b)
  • test: describe the source-only lints' input contract (#339) (de77830)
  • test: replace the dead phiX example for running a regression test (#345) (d3d9a53)

For packagers

A vendored source tarball (all submodules bundled, no .git/ directories) is available as a release asset:

  • File: Source_code_including_submodules.tar.gz
  • sha256: a8b8f0c0f785e2a71273b740120545a5396e6155670b78ec15058e6b01d7d875
  • URL: https://github.com/fg-labs/bwa-mem3/releases/download/v0.8.0/Source_code_including_submodules.tar.gz

Downstream package recipes (e.g. bioconda) should pin against this asset rather than GitHub's auto-generated source tarball, which omits submodule contents.