Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
27 commits
Select commit Hold shift + click to select a range
a30fc0c
Reduce durable write checkpoint stalls
MaxAkbarViking Oct 4, 2026
dda959d
Enforce performance guardrail evidence integrity
MaxAkbarViking Oct 4, 2026
ebf0257
Reuse prepared SELECT plans across parameter values
MaxAkbarViking Oct 4, 2026
0dc0a36
Preserve reader catalog snapshots across commits and checkpoints
MaxAkbarViking Oct 4, 2026
fcdfc7e
Enable bounded prepared primary-key ranges for pooled readers
MaxAkbarViking Oct 4, 2026
b0de2b6
Avoid unnecessary leaf read-ahead for bounded ranges
MaxAkbarViking Oct 4, 2026
f82ed0b
Avoid write-only allocations in snapshot pagers
MaxAkbarViking Oct 4, 2026
9af8985
Reduce planner setup and bound ordinary primary-key reads
MaxAkbarViking Oct 5, 2026
d55c5d9
Allocate table-scan batches on demand
MaxAkbarViking Oct 5, 2026
b1eb30f
Record matched prepared-range latency diagnostic
MaxAkbarViking Oct 5, 2026
92716df
Forward intact LIMIT batches before copying rows
MaxAkbarViking Oct 5, 2026
30c3a01
Fix mixed LIMIT traversal and stabilize allocation guard
MaxAkbarViking Oct 5, 2026
f94ce04
Reuse cancellation state across successful leaf prefetches
MaxAkbarViking Oct 5, 2026
26a5559
Cover buffered row contracts and record rejected optimization
MaxAkbarViking Oct 5, 2026
3156bad
Improve primary-key mutations and preserve storage page ownership
MaxAkbarViking Oct 6, 2026
4e59beb
perf: eliminate per-row ID observer allocations
MaxAkbarViking Oct 6, 2026
19ffabe
perf: reuse insert column ordinals per statement
MaxAkbarViking Oct 6, 2026
860d7ee
perf: skip redundant canonical assignment conversions
MaxAkbarViking Oct 6, 2026
fa1db5b
Checkpoint performance results and isolated WAL research
MaxAkbarViking Oct 7, 2026
7a975f9
Prepare v4.6.6 release candidate
MaxAkbarViking Oct 7, 2026
df84a72
Update release notes for v4.6.6, improve performance descriptions and…
MaxAkbarViking Oct 7, 2026
40851d7
Fix WAL checkpoint finalization racing with conflict reads
MaxAkbarViking Oct 11, 2026
8bc0d09
Update NuGet dependencies while retaining compatible OpenAPI version
MaxAkbarViking Oct 11, 2026
f6d65ab
Document v4.6.6 WAL concurrency fix and dependency updates
MaxAkbarViking Oct 11, 2026
678ba68
Align storage and query documentation with v4.6.6
MaxAkbarViking Oct 11, 2026
864c768
Align SQL Server packaging with updated dependencies
MaxAkbarViking Oct 11, 2026
a826afa
Allow more time for hosted benchmark builds
MaxAkbarViking Oct 11, 2026
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
116 changes: 82 additions & 34 deletions .github/workflows/perf-guardrails.yml
Original file line number Diff line number Diff line change
Expand Up @@ -5,72 +5,120 @@ on:
paths:
- "src/**"
- "tests/CSharpDB.Benchmarks/**"
- "tests/CSharpDB.Benchmarks.Tests/**"
- "global.json"
- "**/*.props"
- "**/*.targets"
- "**/*.csproj"
- "**/packages.lock.json"
- "**/packages.config"
- "**/[Nn]u[Gg]et.[Cc]onfig"
- ".config/dotnet-tools.json"
- ".github/workflows/perf-guardrails.yml"
workflow_dispatch:
inputs:
fail_on_regression:
description: "Fail run when guardrails are violated"
description: "Fail timing regressions (evidence integrity always enforced)"
required: false
default: false
type: boolean
baseline_snapshot:
description: "Optional baseline snapshot folder name (for example 20260302-001757)"
base_ref:
description: "Product base ref (default: head parent; PRs use the PR base SHA)"
required: false
default: ""
type: string
schedule:
- cron: "0 10 * * *"

permissions:
contents: read

jobs:
perf-guardrails:
runs-on: windows-latest
timeout-minutes: 240

timeout-minutes: 360
steps:
- name: Checkout
- name: Checkout harness
uses: actions/checkout@v7
with:
ref: ${{ github.event.pull_request.head.sha || github.sha }}
fetch-depth: 2

- name: Resolve product revisions
id: revisions
shell: pwsh
env:
PR_BASE_SHA: ${{ github.event.pull_request.base.sha }}
REQUESTED_BASE_REF: ${{ inputs.base_ref }}
run: |
$head = (git rev-parse HEAD).Trim()
if ($LASTEXITCODE -ne 0) { throw 'Could not resolve head.' }
if ($env:PR_BASE_SHA) { $base = $env:PR_BASE_SHA }
elseif ($env:REQUESTED_BASE_REF) {
git fetch --no-tags origin $env:REQUESTED_BASE_REF
if ($LASTEXITCODE -ne 0) { throw 'Could not fetch requested base.' }
$base = (git rev-parse FETCH_HEAD).Trim()
}
else { $base = (git rev-parse HEAD^).Trim() }
if ($LASTEXITCODE -ne 0 -or $base -notmatch '^[a-f0-9]{40}$') { throw 'Could not resolve base.' }
"base=$base" >> $env:GITHUB_OUTPUT
"head=$head" >> $env:GITHUB_OUTPUT

- name: Checkout base product
uses: actions/checkout@v7
with:
ref: ${{ steps.revisions.outputs.base }}
path: .tmp/perf-guardrails/base

- name: Setup .NET
- name: Checkout head product
uses: actions/checkout@v7
with:
ref: ${{ steps.revisions.outputs.head }}
path: .tmp/perf-guardrails/head

- name: Setup head .NET SDK
uses: actions/setup-dotnet@v6
with:
global-json-file: global.json

- name: Run Perf Guardrails PR Lane (Report)
if: github.event_name == 'pull_request'
shell: pwsh
run: |
pwsh ./tests/CSharpDB.Benchmarks/scripts/Run-Perf-Guardrails.ps1 `
-Configuration Release `
-Mode pr `
-NoFailOnRegression `
-BaselineSnapshot "${{ inputs.baseline_snapshot }}"
- name: Setup base .NET SDK
uses: actions/setup-dotnet@v6
with:
global-json-file: .tmp/perf-guardrails/base/global.json

- name: Run Perf Guardrails Release Lane (Report)
if: github.event_name != 'pull_request' && (github.event_name != 'workflow_dispatch' || inputs.fail_on_regression != true)
- name: Test guardrail integrity contract
shell: pwsh
run: |
pwsh ./tests/CSharpDB.Benchmarks/scripts/Run-Perf-Guardrails.ps1 `
-Configuration Release `
-Mode release `
-NoFailOnRegression `
-BaselineSnapshot "${{ inputs.baseline_snapshot }}"
run: ./tests/CSharpDB.Benchmarks/scripts/Test-PerfGuardrails.ps1

- name: Run Perf Guardrails Release Lane (Gate)
if: github.event_name == 'workflow_dispatch' && inputs.fail_on_regression == true
- name: Run balanced base and head guardrails
shell: pwsh
env:
PERF_EVENT: ${{ github.event_name }}
FAIL_ON_REGRESSION: ${{ inputs.fail_on_regression }}
run: |
pwsh ./tests/CSharpDB.Benchmarks/scripts/Run-Perf-Guardrails.ps1 `
-Configuration Release `
-Mode release `
-BaselineSnapshot "${{ inputs.baseline_snapshot }}"
$mode = if ($env:PERF_EVENT -eq 'pull_request') { 'pr' } else { 'release' }
$reportOnly = $env:FAIL_ON_REGRESSION -ne 'true'
./tests/CSharpDB.Benchmarks/scripts/Run-PairedPerfGuardrails.ps1 `
-BaseRoot .tmp/perf-guardrails/base `
-HeadRoot .tmp/perf-guardrails/head `
-OutputPath .tmp/perf-guardrails/evidence `
-Configuration Release -Mode $mode -NoFailOnRegression:$reportOnly `
-MicroArguments @('--warmupCount', '2', '--iterationCount', '3', '--iterationTime', '100', '--buildTimeout', '600')

- name: Upload Perf Artifacts
if: always()
uses: actions/upload-artifact@v7
with:
name: perf-guardrails-${{ github.run_id }}
if-no-files-found: error
include-hidden-files: true
path: |
tests/CSharpDB.Benchmarks/results/perf-guardrails-last.md
tests/CSharpDB.Benchmarks/results/perf-guardrails-run-logs/*.log
BenchmarkDotNet.Artifacts/results/*.csv
BenchmarkDotNet.Artifacts/*.log
.tmp/perf-guardrails/evidence/
BenchmarkDotNet.Artifacts/
tests/CSharpDB.Benchmarks/BenchmarkDotNet.Artifacts/
.tmp/perf-guardrails/base/BenchmarkDotNet.Artifacts/
.tmp/perf-guardrails/base/tests/CSharpDB.Benchmarks/BenchmarkDotNet.Artifacts/
.tmp/perf-guardrails/head/BenchmarkDotNet.Artifacts/
.tmp/perf-guardrails/head/tests/CSharpDB.Benchmarks/BenchmarkDotNet.Artifacts/
.tmp/perf-guardrails/base/tests/CSharpDB.Benchmarks/results/perf-guardrails-run-logs/
.tmp/perf-guardrails/head/tests/CSharpDB.Benchmarks/results/perf-guardrails-run-logs/
88 changes: 43 additions & 45 deletions RELEASE_NOTES.md
Original file line number Diff line number Diff line change
@@ -1,47 +1,45 @@
# What's New

## CSharpDB 4.6.5

CSharpDB 4.6.5 adds a Privacy & Retention workflow in Studio, opens the
Storage Inspector without an initial full-file scan, and improves SQL editor
completion and storage write paths. These notes cover changes since v4.6.4.

### Privacy & Retention

- Create and save reusable policies that select records with typed conditions,
date rules, and explicitly mapped related records. Search, duplicate, import,
and export policies in **Data Hygiene → Privacy & Retention**.
- Choose fields to erase, replace with a constant or stable anonymous value, or
partially mask. Preview eligible records, changed counts, preserved fields,
warnings, and bounded before/after samples before applying a policy.
- Apply a prepared policy in one transaction with bounded batches and
cancellation before commit. Review committed run receipts and reconcile an
uncertain commit outcome before retrying.
- Protect keys and relationship columns, reject unsupported constraints or
mutation callbacks during preparation, and keep records and their declared
relationships intact.

### Studio and storage improvements

- Open Storage Inspector with a persisted summary. Full page and WAL analysis
now starts only when **Analyze storage** is requested, with cancellation.
- Restore context-aware SQL editor suggestions for tables, columns, and
keywords, and expand the supported keyword completion set.
- Reuse WAL snapshot segments and share immutable snapshot maps to reduce
copying during concurrent reads. Streamline simple INSERT execution and
checkpoint storage paths.
- Refresh the .NET SDK and selected runtime, tooling, and test dependencies.

### Compatibility and scope

- No database file-format revision is introduced by these changes.
- The initial Privacy & Retention workflow supports a single standard
file-backed direct database, including durable hybrid storage. Remote,
sharded, memory-only, and snapshot-only hybrid execution are outside its
scope. It changes selected live fields; it does not delete records, discover
unselected personal-data copies, or establish that a person is unidentifiable.
- Privacy runs require an exclusive writable file session. Other writable
handles can prevent preparation or apply from starting. Review the policy,
preview, and run outcome before retrying a failed or uncertain operation.
- Storage analysis remains an explicit potentially long-running operation.
The initial summary does not include results of a full integrity scan.
## CSharpDB 4.6.6

CSharpDB 4.6.6 improves durable write throughput, prepared queries, and bounded
primary-key reads while strengthening reader snapshot, buffered-row, and concurrent
WAL-read correctness.
These notes cover changes since v4.6.5.

### Query and write improvements

- Reuse prepared SELECT plans across parameter values and support bounded integer
primary-key ranges through pooled readers and ordinary queries.
- Preserve reader catalog snapshots across commits and checkpoints, including
schema metadata used by existing readers.
- Reduce table-scan, LIMIT, snapshot-pager, and leaf-prefetch allocations. Forward
intact row batches while preserving ownership and mixed row/batch traversal.
- Streamline primary-key mutations and INSERT execution by reusing column ordinals,
avoiding per-row observer allocations, and skipping redundant canonical value
conversions.
- Reduce durable-write checkpoint stalls and improve WAL/checkpoint lifecycle
handling and storage-page ownership.

### Storage correctness

- Prevent checkpoint reset or retained-tail compaction from invalidating WAL
offsets used during write-conflict resolution. This fixes a concurrency race
that could cause short WAL reads or return incorrect page contents.
- Defer checkpoint finalization while durable commits still have unpublished WAL
offsets, preserving correct reads after those commits complete.
- Add deterministic regression coverage for reset and compaction, including stale
offsets that remain within file bounds, cancellation, lock release, and forward
progress. The database and WAL formats are unchanged.

### Dependencies and maintenance

- Update gRPC/Protobuf, SQL Server migration dependencies, WebView2, OpenTelemetry,
Scalar, and test tooling.
- Retain Microsoft.OpenApi 2.12.0 for compatibility with
Microsoft.AspNetCore.OpenApi 10.0.12 on .NET 10.

### Performance guardrails

- Validate performance evidence integrity and reject incomplete or inconsistent
comparison evidence.
Original file line number Diff line number Diff line change
Expand Up @@ -74,7 +74,7 @@ for REQUIRED_FILE in \
README.md \
adapters/sqlserver/csharpdb-migration-sqlserver-worker \
adapters/sqlserver/THIRD-PARTY-NOTICES.md \
adapters/sqlserver/licenses/Microsoft.Data.SqlClient.SNI.runtime-6.0.3-LICENSE.txt \
adapters/sqlserver/licenses/Microsoft.Data.SqlClient.SNI.runtime-7.1.0-LICENSE.txt \
adapters/mysql/csharpdb-migration-mysql-worker \
adapters/mysql/THIRD-PARTY-NOTICES.md
do
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -173,7 +173,7 @@ $requiredFiles = @(
(Join-Path $sourceRoot 'README.md'),
(Join-Path $sourceRoot 'adapters/sqlserver/csharpdb-migration-sqlserver-worker.exe'),
(Join-Path $sourceRoot 'adapters/sqlserver/THIRD-PARTY-NOTICES.md'),
(Join-Path $sourceRoot 'adapters/sqlserver/licenses/Microsoft.Data.SqlClient.SNI.runtime-6.0.3-LICENSE.txt'),
(Join-Path $sourceRoot 'adapters/sqlserver/licenses/Microsoft.Data.SqlClient.SNI.runtime-7.1.0-LICENSE.txt'),
(Join-Path $sourceRoot 'adapters/mysql/csharpdb-migration-mysql-worker.exe'),
(Join-Path $sourceRoot 'adapters/mysql/THIRD-PARTY-NOTICES.md'),
(Join-Path $sourceRoot 'adapters/access/csharpdb-migration-access-worker.exe'),
Expand Down
2 changes: 2 additions & 0 deletions docs/README.md
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,8 @@
- [Public user guides](../www/docs/index.html)
- [Release notes](../RELEASE_NOTES.md)
- [Changelog and downloads maintenance](releases/changelog-maintenance.md)
- [Performance checkpoint: October 6, 2026](design/performance-checkpoint-2026-10-06.md)
- [Draft WAL recovery boundary and bounded reclamation](design/wal-reclamation.md)

The website source is in `www/`. Shared documentation images are in `docs/images/`.
The release publication inventories in `docs/releases/` support the documentation validation scripts.
Loading