Skip to content

perf(snapshot): bypass placeholder matcher for literals #985

Description

@Chemaclass

Summary

bashunit::snapshot::compare sends every existing snapshot through
bashunit::snapshot::match_with_placeholder, even when the stored value does not
contain BASHUNIT_SNAPSHOT_PLACEHOLDER.

That matcher builds a regex with sed, then invokes Perl (or grep when Perl is
unavailable). Literal snapshots therefore pay external-process costs on every
successful assertion, despite needing only a Bash string comparison.

This is the main success-path cost left after #775 removed the path-resolution,
normalization and file-read forks.

Evidence

At 448da9b8, 200 direct calls on an identical literal value:

current matcher:     1.05s
literal fast path:  <0.01s
placeholder matcher: 1.21s

The existing release benchmark also reports 500 snapshot assertions at roughly
3 seconds, so this path is material in real suites.

Proposal

Inspect the stored snapshot before selecting the comparison strategy:

  • no configured placeholder: compare with Bash [ "$actual" = "$snapshot" ]
  • placeholder present: retain the existing Perl/grep matcher and its multiline
    semantics

Apply the same routing to matching and mismatching literal snapshots. A plain
mismatch needs a diff, not a regex engine.

Constraints

  • Bash 3.0+
  • Existing snapshots and placeholder semantics remain byte-compatible
  • The normal literal path must not invoke sed, Perl or grep
  • Do not weaken the no-Perl fallback
  • Keep failure rendering unchanged

Acceptance criteria

  • Matching literal snapshots bypass match_with_placeholder
  • Mismatching literal snapshots also bypass it and render the existing diff
  • Placeholder snapshots still use the existing matcher
  • Custom BASHUNIT_SNAPSHOT_PLACEHOLDER values still work
  • A regression test proves the literal path does not call the placeholder matcher
  • Benchmark the literal path before/after and record the result in the PR
  • Update CHANGELOG.md under ## Unreleased
  • make sa · make lint · ./bashunit --parallel --simple --strict tests/ · bash build.sh bin -v

Metadata

Metadata

Assignees

No one assigned

    Labels

    Type

    No type

    Projects

    Status
    Done

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions