BenchmarksBatch Processing Benchmarks

Batch Processing Benchmarks

Batch benchmarks time a complete directory run: parsing, SASA calculation, output writing and worker scheduling. The runs use zsasa 0.9.0, pinned comparator builds and 128 sphere points; rows measured with a later release name it. The comparator builds did not change between zsasa releases, so their timings are retained from the 0.6.0 session on the same machine.

FreeSASA has no native directory mode, so its rows use a thin freesasa_batch wrapper around the pinned FreeSASA C API.

Throughput and memory#

Throughput against peak memory

10 threads, 128 sphere points. Points are three-run means; whiskers show one standard deviation. Higher and further left is better.
Data table

On both proteomes the zsasa bitmask modes sit in the top-left corner: the highest throughput at the lowest peak memory. The exact f64 and f32 modes are faster than FreeSASA batch and RustSASA while using a quarter of their memory or less.

Batch throughput and memory at 10 threads

128 sphere points. Bars are three-run means; whiskers show one standard deviation. SwissProt was measured once, under the passive disk I/O policy.
Data table

E. coli AFDB#

ToolRuntime (s)Structures/sPeak RSS (MiB)vs FreeSASA batchvs RustSASAvs Lahuta bitmask
zsasa f644.2581,02647.93.05×1.34×0.53×
zsasa f324.2281,03444.83.08×1.35×0.53×
zsasa bitmask f641.4852,94350.28.76×3.85×1.52×
zsasa bitmask f321.4453,02347.49.00×3.95×1.56×
FreeSASA batch13.008336212.21.00×0.44×0.17×
RustSASA5.713765170.12.28×1.00×0.39×
Lahuta7.573577192.21.72×0.75×0.30×
Lahuta bitmask2.2561,937182.25.77×2.53×1.00×

E. coli AFDB: 4,370 structures, 10 threads, 128 sphere points.

Human AFDB#

ToolRuntime (s)Structures/sPeak RSS (MiB)vs FreeSASA batchvs RustSASAvs Lahuta bitmask
zsasa f6443.41454384.93.13×1.50×0.46×
zsasa f3242.74255280.93.18×1.53×0.47×
zsasa bitmask f6413.6871,72389.69.93×4.77×1.47×
zsasa bitmask f3213.4081,75984.210.14×4.87×1.50×
FreeSASA batch135.903174682.21.00×0.48×0.15×
RustSASA65.321361330.32.08×1.00×0.31×
Lahuta74.171318358.71.83×0.88×0.27×
Lahuta bitmask20.0701,175336.56.77×3.25×1.00×

Human AFDB: 23,586 structures, 10 threads, 128 sphere points.

The "vs" columns are runtime ratios: the comparator's runtime divided by the row's runtime.

Thread scaling#

E. coli AFDB throughput by thread count

4,370 structures, 128 sphere points. Points are three-run means with one standard deviation.
Data table

From 1 to 10 threads, zsasa f64 and bitmask f32 both gain a factor of about 6.9 on a machine with 4 performance and 6 efficiency cores. FreeSASA batch peaks at 4 threads, and Lahuta bitmask stops improving between 8 and 10.

Beyond the core count#

zsasa accepts more worker threads than the machine has cores. The benchmark machine has 10 logical CPUs, so 20 and 40 workers are overcommitted.

zsasa beyond the core count

Worker counts above the 10 logical CPUs of the benchmark machine, at 128 sphere points. Three-run means, except SwissProt, which was measured once under the passive disk I/O policy. Busy cores is CPU time divided by wall time.
Data table

On the E. coli and Human runs, extra workers leave throughput unchanged within about 2% and raise peak memory roughly in proportion to the worker count. SwissProt is the exception: bitmask throughput is about 10% higher at 20 workers.

The "Busy cores" metric shows why. The E. coli and Human collections occupy 0.8 and 9.1 GB on disk and fit in the file cache of the 32 GB machine, and zsasa keeps about 9 of the 10 cores busy on them. SwissProt occupies 119 GB, and with 10 workers the bitmask run keeps only 3.4 cores busy on average, 4.1 with 40 workers. The idle workers wait inside open(): the benchmark machine runs endpoint-security software that scans every file when it is first opened (see SwissProt AFDB). Using more workers than cores is therefore an option for runs that wait on file access, not a general setting.

Human AFDB, mmCIF input#

The mmCIF runs compare two parser paths, the generic mmCIF parser and a fast path for AlphaFold models ("AF fast"), with two input strategies, reading the whole file or memory-mapping it. All four are bitmask f32 runs of zsasa 0.11.0: batch runs of 0.9.0 to 0.10.1 ignored --input-io, so the comparison needs the later release. Lahuta was measured in the same session.

ToolRuntime (s)Structures/sPeak RSS (MiB)vs Lahuta bitmask
zsasa 0.11.0 generic/read17.2111,370140.60.94×
zsasa 0.11.0 generic/mmap17.2171,370127.20.94×
zsasa 0.11.0 AF fast/read15.4221,52994.91.05×
zsasa 0.11.0 AF fast/mmap15.4071,53184.01.05×
Lahuta bitmask16.1861,457343.41.00×

Human AFDB, mmCIF: 23,586 structures, 10 threads, 128 sphere points.

The AF fast path is about 5% ahead of Lahuta bitmask at under a third of its peak memory, and the generic parser is about 6% behind. Reading and memory-mapping the input take the same time within 2% on this warm-cache run; memory-mapping has the lower peak memory, 84 against 95 MiB for the AF fast path at 10 threads and 244 against 323 MiB at 40 workers.

SwissProt AFDB#

SwissProt is the largest dataset, 550,122 structures. Each configuration was measured once, so this section reports single observations without an uncertainty estimate.

The benchmark machine scans every file when it is first opened, and this collection is too large for its files to stay cached and scanned between runs. macOS also slows that scan down while a tool reads from the same disk with the default I/O policy. The SwissProt commands were therefore run under the passive disk I/O policy (taskpolicy -d passive), for zsasa and Lahuta alike.

ToolRuntime (s)Structures/sPeak RSS (MiB)vs Lahuta bitmask
zsasa 0.9.0 f32804.299684270.30.61×
zsasa 0.9.0 bitmask f32460.5891,194272.81.06×
zsasa 0.11.0 bitmask f32398.1181,382291.51.23×
Lahuta bitmask487.9271,127692.01.00×

SwissProt AFDB: 550,122 structures, 10 threads, 128 sphere points.

At 10 threads zsasa 0.9.0 bitmask f32 processes the collection in 7.7 minutes, about 6% faster than Lahuta bitmask at 40% of its peak memory. Lahuta's bitmask SASA mode reads only AlphaFold models and was measured at 10 threads; it has no equivalent of worker overcommit. With 20 and 40 workers zsasa 0.9.0 bitmask f32 reaches 1,312 and 1,283 structures/s at 343 and 472 MiB.

The zsasa 0.11.0 row is one run of the later release under the same policy. From 0.11.0 on a batch reads each input with one read instead of memory-mapping it, which shortens the wait for files on collections larger than memory. The release also adds --passive-io, which requests the passive policy from within zsasa.

Under the default I/O policy both tools are slower on this machine and the order at 10 threads is reversed: zsasa 0.9.0 bitmask f32 runs at 821 structures/s and Lahuta bitmask at 935. The investigation notes in the benchmark repository have the measurements behind this.

Reproducing these results#

The charts and tables on this page are generated from results/tables/batch_t10_summary.csv and batch_thread_scaling.csv in N283T/zsasa-benchmarks, which also holds the full harness and manifests.

Edit this page