Performance

PySeq’s performance matters most in sequence discovery and lss over large file sets.

This project uses two complementary approaches:

The regression tests should stay stable and fast enough for normal CI. The benchmark runner is for collecting timing and profiling data over time, not for enforcing fragile micro-optimizations in every pull request.

Benchmark Runner

Current benchmark entry point:

Simple examples:

python scripts/benchmark.py
python scripts/benchmark.py --full
python scripts/benchmark.py --json /tmp/pyseq-main.json
python scripts/benchmark.py --scenarios contiguous,mixed
python scripts/benchmark.py --path /project/shot/frames --iterations 5
python scripts/benchmark.py --path /project/shot/frames --glob "*.exr" --iterations 5
python scripts/benchmark.py --compare /tmp/pyseq-main.json /tmp/pyseq-feature.json

What it measures:

Synthetic scenarios:

When using --path, the runner benchmarks an existing directory instead of a synthetic dataset. This is useful for validating results against real-world sequence layouts that may not be modeled well by generated fixtures.

Default synthetic dataset sizes:

Default synthetic scenarios:

You can override dataset sizes or iteration count:

python scripts/benchmark.py --sizes 100,1000,10000,50000 --iterations 7
python scripts/benchmark.py --sizes 1000,10000 --scenarios mixed --iterations 7

Local A/B Comparison

Use the same machine and same interpreter for both runs.

Example workflow:

# on baseline branch
python scripts/benchmark.py --full --json /tmp/pyseq-main.json

# switch branches
python scripts/benchmark.py --full --json /tmp/pyseq-feature.json

# compare
python scripts/benchmark.py --compare /tmp/pyseq-main.json /tmp/pyseq-feature.json

For real-world validation, use the same workflow against an existing directory:

# on baseline branch
python scripts/benchmark.py --path /project/shot/frames --iterations 5 --json /tmp/pyseq-main.json

# switch branches
python scripts/benchmark.py --path /project/shot/frames --iterations 5 --json /tmp/pyseq-feature.json

# compare
python scripts/benchmark.py --compare /tmp/pyseq-main.json /tmp/pyseq-feature.json

Benchmark Hygiene

Before trusting an A/B result, make sure both runs use:

The benchmark summary and JSON now record:

Check those fields before drawing conclusions from a comparison. If they do not match your expectations, fix the environment first and rerun.

Profiling

Profiling is enabled by default, but it runs in a separate pass after the timed measurements. That means the timing samples stay clean while we still capture where time is going.

Generated artifacts:

Default output location:

Useful options:

CI Automation

The GitHub Actions benchmark workflow runs pull request comparisons in one job on one GitHub-hosted runner.

For pull requests it:

On pull requests, benchmark-pr is the authoritative check. The separate benchmark-branch job is only for non-PR runs such as scheduled or manual benchmark collection, so seeing it skipped on a pull request is expected.

The pull request suite uses synthetic datasets only, so it is best treated as a regression guardrail. For more realistic validation, keep using local --path runs against representative production-style directories.

Current benchmark policy:

Result Format

The benchmark runner can emit machine-readable JSON for local comparison, CI artifacts, or published reports.

Example run payload:

{
  "benchmarks": {
    "get_sequences_dir_1000": {
      "iterations": 5,
      "max_s": 0.043512,
      "mean_s": 0.041932,
      "median_s": 0.041704,
      "min_s": 0.040161,
      "samples_s": [0.040161, 0.041085, 0.041704, 0.043198, 0.043512]
    },
    "lss_1000": {
      "iterations": 5,
      "max_s": 0.139424,
      "mean_s": 0.133529,
      "median_s": 0.132611,
      "min_s": 0.129400,
      "samples_s": [0.129400, 0.131818, 0.132611, 0.134390, 0.139424]
    }
  },
  "branch": "feat/example",
  "commit": "abc1234",
  "iterations": 5,
  "kind": "benchmark",
  "lib_root": "/path/to/pyseq/lib",
  "platform": "Linux-6.x-x86_64",
  "profiled": true,
  "pyseq_file": "/path/to/pyseq/lib/pyseq/__init__.py",
  "pyseq_seq_file": "/path/to/pyseq/lib/pyseq/seq.py",
  "python_executable": "/path/to/venv/bin/python",
  "profiles_dir": "tmp/benchmarks/profiles/20260721T000000Z-feat-example-abc1234",
  "python": "3.11.x",
  "repo_root": "/path/to/pyseq",
  "scenarios": ["contiguous", "mixed"],
  "script_path": "/path/to/pyseq/scripts/benchmark.py",
  "sizes": [100, 1000, 10000],
  "timestamp_utc": "2026-07-21T00:00:00+00:00"
}

Field notes:

Methodology

The benchmark runner:

This keeps the results useful without pretending that a shared CI runner is a perfect benchmarking machine.

Interpreting Results

Treat GitHub-hosted benchmark numbers as trend indicators, not as precise absolute truth.

Good uses:

Less reliable uses:

If stronger consistency becomes important, prefer a self-hosted benchmark runner with a stable machine configuration.

Latest Benchmarks

This section is generated automatically by the docs publishing workflow, which runs scripts/benchmark.py for the current workflow ref before building the Pages site.

pyseq benchmarks

Branch: master Commit: 7de4bb5 Sizes: 100,1000,10000 Iterations: 5 Repo: /home/runner/work/pyseq/pyseq Lib: /home/runner/work/pyseq/pyseq/lib Python: /opt/hostedtoolcache/Python/3.11.16/x64/bin/python Scenarios: contiguous,mixed PySeq: /home/runner/work/pyseq/pyseq/lib/pyseq/__init__.py PySeq seq: /home/runner/work/pyseq/pyseq/lib/pyseq/seq.py Profiles: /home/runner/work/pyseq/pyseq/tmp/benchmarks/profiles/20260824T021302Z-master-7de4bb5

Benchmark Median (s) Mean (s) Min (s) Max (s)
get_sequences_list_contiguous_100 0.001755 0.001758 0.001734 0.001807
get_sequences_dir_contiguous_100 0.001993 0.001992 0.001977 0.002015
lss_contiguous_100 0.032087 0.032165 0.031853 0.032690
resolve_sequence_contiguous_100 0.001917 0.001935 0.001912 0.001973
get_sequences_list_mixed_100 0.002183 0.002208 0.002170 0.002301
get_sequences_dir_mixed_100 0.002431 0.002443 0.002425 0.002464
lss_mixed_100 0.032843 0.033168 0.032690 0.033858
resolve_sequence_mixed_100 0.001476 0.001482 0.001447 0.001535
get_sequences_list_contiguous_1000 0.017569 0.017631 0.017478 0.017835
get_sequences_dir_contiguous_1000 0.019354 0.019424 0.019312 0.019752
lss_contiguous_1000 0.051347 0.051359 0.051184 0.051604
resolve_sequence_contiguous_1000 0.018404 0.019022 0.018327 0.021519
get_sequences_list_mixed_1000 0.016787 0.016807 0.016657 0.016983
get_sequences_dir_mixed_1000 0.018682 0.018682 0.018565 0.018842
lss_mixed_1000 0.050616 0.050751 0.050442 0.051118
resolve_sequence_mixed_1000 0.013885 0.014460 0.013830 0.016834
get_sequences_list_contiguous_10000 0.183487 0.183412 0.178488 0.187582
get_sequences_dir_contiguous_10000 0.201005 0.202347 0.197625 0.210448
lss_contiguous_10000 0.240787 0.239694 0.236590 0.241294
resolve_sequence_contiguous_10000 0.189188 0.188787 0.186541 0.191101
get_sequences_list_mixed_10000 0.169957 0.169903 0.166632 0.171788
get_sequences_dir_mixed_10000 0.188948 0.188880 0.187347 0.190658
lss_mixed_10000 0.226073 0.226971 0.225747 0.231167
resolve_sequence_mixed_10000 0.139818 0.140970 0.138969 0.143844

Downloads