Skip to content

Remove per-argument base64 round trips from data provider parsing #1370

Description

@Chemaclass

Data-provider tests should preserve their arguments without encoding each argument in one subprocess and decoding it in another. The current internal transfer makes provider-heavy suites several times slower than ordinary tests with the same assertion work.

The parser base64-encodes each argument; the caller decodes each one before dispatch. For 100 rows of two nonempty arguments, the run launches 400 base64 processes for this round trip, 200 tr processes and 100 grep processes, plus the one startup base64 probe. The sequential provider fixture took 1,825 ms versus 475 ms for 100 ordinary passing tests.

Measured on macOS arm64, Bash 3.2.57, bashunit 0.51.0 at 860c797a48e34be20b019a70f58c0e06d15c8d33. Wall times are medians of five runs after one warm-up, with the same fixtures, working directory, output mode and bootstrap settings. External command counts come from PATH shims, not re-echoed shell traces.

Replace the internal argument transfer with a lossless representation that avoids per-argument codec processes. NUL-delimited fields through run-owned scratch storage are one candidate: builtin read -r -d '' round-tripped empty fields, embedded newlines, backslashes and a unit separator in focused checks on Bash 3.00.22 and 3.2.57. This is a candidate, not a required design.

The parser currently runs inside command substitution. Preserve that isolation for its eval and expansions; moving evaluation directly into the parent can leak shell side effects. Keep the public provider/data_set API, evaluation rules and row order unchanged.

  • Existing provider functional tests pass unchanged in sequential and parallel modes, including %q, quoted empty arguments and sentinel handling, spaces, tabs, embedded newlines, trailing whitespace/backslashes and literal metacharacters.
  • A regression pins parser evaluation side effects remaining isolated from the runner.
  • Ordinary two-argument rows require no external base64 encode/decode process per argument.
  • Hooks which change directory, repeated/retried tests, interpolation and missing/empty providers retain their behavior.
  • Temporary argument storage remains collision-free under parallel execution and is cleaned with the run.
  • Benchmark short rows, varying argument counts and large values; retain the optimization only with a measured benefit and no material large-value regression.
  • The full compatibility/local gates pass.

Keep Bash 3.0 as the minimum. Verify the source runner and standalone artifact, actual Bash 3.0 in sequential, parallel, simple, simple-parallel and strict modes, macOS Bash 3.2, make test, make test/parallel, make test/strict, make sa and make lint. Measure with the same benchmark on current main and the final branch; keep elapsed-time checks out of normal tests.

Related: #509 pins empty-argument behavior, #529 pins directory changes, and #763 removed repeated provider lookup scans. This issue is argument transport, not another annotation scanner or a parser/API redesign.

Activity

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Metadata

Metadata

Assignees

Labels

enhancementNew feature or request

Type

No type

Projects

  • Status
    Done

Milestone

No milestone

Relationships

None yet

Development

No branches or pull requests

Issue actions