Skip to content

perf(state): avoid base64 forks for empty title and hook message in export_subshell_context #762

Closed

Description

@Chemaclass

Part of #761.

Problem

Every test run encodes its subshell context once per test in bashunit::state::export_subshell_context (src/state.sh:231-259). It always forks three echo -n ... | base64 pipelines (src/state.sh:239-246) for _BASHUNIT_TEST_OUTPUT, _BASHUNIT_TEST_TITLE, and _BASHUNIT_TEST_HOOK_MESSAGE, even though title and hook message are empty for almost every test. On the decode side, bashunit::helper::decode_base64 (src/helpers.sh:149) already has a fast path for the _BASHUNIT_EMPTY_ marker, but a plain empty string still forks printf | base64 -d, and bashunit::runner::decode_subshell_output (src/runner.sh:1110) runs once per test.

Measured cost: each pipeline is ~1.6ms (2 forks) on macOS bash 3.2. That is ~4-5ms per test, ~5s across the ~1160-test suite, and it compounds inside the 258 nested ./bashunit runs in the acceptance suite.

Task

  1. In export_subshell_context, only fork base64 when the source variable is non-empty; emit an empty string (or the existing _BASHUNIT_EMPTY_ marker, whichever keeps the wire format consistent — check how ##TEST_TITLE=/##TEST_HOOK_MESSAGE= are parsed downstream in src/runner.sh and src/parallel.sh) for empty values. Note echo -n "" | base64 already produces an empty string, so guarding with [ -n "$var" ] should be wire-compatible; verify against the parallel .result file path too (bashunit::runner::parse_result_parallel, src/runner.sh:1441).
  2. In decode_base64, add an early return for empty input so "" never forks.
  3. Audit callers of decode_base64 for other per-test empty decodes.

Tests first (TDD)

  • Unit tests for encode/decode round-trip: empty string, plain string, multiline string, string with ANSI codes, UTF-8. Follow patterns in tests/unit/helpers_test.sh / existing state tests.
  • Regression: a test with a # @test_title annotation and a hook message still renders correctly (sequential AND --parallel), since those exercise the non-empty paths.

Constraints

  • Bash 3.0+ only: no declare -A, no [[ ]], no ${var,,}, no negative array indexing, no &>>.
  • Wire format of ##ASSERTIONS_*##TEST_* context string must remain parseable by the existing extractors; do not change field order.
  • Keep the Alpine base64 -w 0 branch behavior (src/state.sh:237-241).

Acceptance criteria

  • ./bashunit tests/ and ./bashunit --parallel tests/ pass.
  • make sa, make lint pass; shfmt -w . produces no diff.
  • Fork census (see tracking issue) shows base64 count drops from ~4/test to ~2/test for tests without title/hook message.
  • Before/after timing of the 100-noop benchmark reported in the PR.

Line references valid at commit 4d80e7c.

Activity

  1. Chemaclass commented on Jul 12, 2026

    @Chemaclass
    MemberAuthor

    Landed in PR #768 (902fcb3). Verified at 1ae3e82: export_subshell_context only forks base64 for non-empty values and decode_base64 short-circuits empties. Follow-up per-assertion/per-test fork work continues in #772/#774.

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

Metadata

Metadata

Assignees

No one assigned

    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