microsoft / microsoft/mssql-rs

mssql-odbc: single-row bound fetch regressed ~17% against the pinned perf baseline

Open
#507 0 comments 0 reactions 0 assignees View on GitHub

Nobody has claimed this yet.

bug
Dominant language
Rust
Stars
53
Forks
14
Avg merge
1d 15h
Merged PRs (30d)
137

Description

Describe the bug

The ODBC perf pipeline (pipeline 2325) flagged a confirmed regression against the pinned mssql-odbc baseline in run 20260905.1 (buildId 172669). The regression is isolated to rowset size 1: the fixed per-call setup cost of SQLFetchScroll grew, and at rowset 1 that cost is paid once per row instead of being amortized across 64 or 1000 rows.

Three changes landed between the last green run (49f2ccb4, run 171863) and the regressed run, and each added fixed work to every fetch:

  1. Descriptor-backed bindings (AB#47437) made every SQLFetchScroll, SQLBindCol, and SQLFreeStmt(SQL_UNBIND) call handles::live_type(ard), which takes the process-global LIVE_HANDLES mutex and does a hash lookup. The bind_cycle workload pays this 17 times per row.
  2. Deferred SQL_C_DEFAULT resolution (#460) acquires the ENV mutex and heap-allocates a Vec<SqlSmallInt> of per-column SQL types on every fetch, whether or not any binding actually uses SQL_C_DEFAULT.
  3. The PLP metadata cache added in e8c4ffa4 was lost in the revert at 49f2ccb4, so fill_rowset re-locks the STMT and rebuilds per-column PLP encoding info on every call.
Steps to reproduce
  1. Build mssql-odbc at 5c412918 (or any commit at or after the merge of #460).
  2. Run the perf-lab benchmark suite against it with the pinned baseline commit from mssql-odbc-bench/perf-lab/baseline-commit.txt:
    • mssql-odbc-bench/perf-lab/run-benchmarks.sh (or run-benchmarks.ps1 on Windows)
  3. Compare the fetch/rowset_100k_c15_fixed/bound_rowset_1 and fetch/rowset_20k_c15_fixed/bind_cycle_rowset_1 medians against the baseline.
Expected behavior

Single-row fetch wall time stays at or below the pinned baseline. Run 171863 had it 17.71% faster than baseline on bound_rowset_1 and 15.55% faster on bind_cycle_rowset_1, so that is the level the driver had already reached.

Actual behavior

Run 172669 measured, as medians over 5 repetitions:

Benchmark Baseline Candidate Delta
fetch/rowset_100k_c15_fixed/bound_rowset_1 141.13 ms 163.56 ms +16.7%
fetch/rowset_20k_c15_fixed/bind_cycle_rowset_1 109.06 ms 123.22 ms +13.2%

Rowset 64 and 1000 variants were flat, and the reported execute_ms and metadata_bind_ms phases were unchanged, which places the cost inside the fetch loop's per-call setup rather than in execution or metadata binding.

Version

commit 5c412918

Affected crate

mssql-odbc

Environment
  • Perf pipeline 2325, run 20260905.1 (buildId 172669)
  • Compared against the baseline commit pinned in mssql-odbc-bench/perf-lab/baseline-commit.txt
Additional context

The pipeline's regression gate fires at 5% higher wall time, and both benchmarks reproduced in the confirmation rounds, so this is not run-to-run noise.

Contributor guide

Open the contributing guide

First steps

  1. Read the whole issue, then the project's contributing guide.
  2. Comment on the issue to say you are picking it up — it saves two people doing the same work.
  3. Fork the repository and make your change on a branch.
  4. Open a pull request that references the issue number.

Research direction

Start with mssql-odbc's fetch loop and the reported per-call setup paths, then run perf-lab/run-benchmarks.sh or run-benchmarks.ps1 using the commit in perf-lab/baseline-commit.txt. Compare bound_rowset_1 and bind_cycle_rowset_1 against the pinned baseline, while checking that rowset 64 and 1000 remain flat. Done means the single-row medians no longer exceed the baseline regression threshold.

Written by the indexing model from the issue text.

Assessment

Tech stack
rust, sql
Domain
backend, databases, performance
Issue type
Bug
Difficulty
4/5
Estimated time
3-5 days
Activity status
Active
Clarity
Mostly clear
Newbie friendliness
52/100

Get new issues in your inbox

A short digest of beginner-friendly GitHub issues.