M6: Native AOT validation and benchmarks (closes Phase 2)#6
Merged
Conversation
IsAotCompatible turns on the trim, single-file, and AOT analyzers, which report zero findings; with TreatWarningsAsErrors on, any future regression fails the build. The flag also stamps the package metadata consumers'' tooling reads when they publish trimmed or Native AOT apps. Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
Trim analysis alone cannot prove AOT compatibility, so CI now publishes a console app with PublishAot and executes the native binary: it exercises every generated shape (list, single, optional, scalar, scalar list, streaming, execute, property-mapped rows) plus SqlSession against real SQLite, with the exit code as the verdict. PublishAot in the project file also keeps the AOT analyzers on for every solution build. Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
Four categories (1000-row list, single row, scalar, execute) run the identical SQL over in-memory SQLite three ways: hand-written ADO.NET as the baseline ceiling, SqlBound generated code, and Dapper, with MemoryDiagnoser since allocations are where reflection-free codegen should show. Benchmarks live under bench/ (convention recorded in architecture.md), join the solution so CI builds them, and are never run in CI. A bench-local Directory.Build.props shields BenchmarkDotNet generated host projects from the repo root defaults, which would otherwise break them with multi-targeting and warning escalation. Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
A full local run backs the docs: SqlBound stays within 1-9% of hand-written ADO.NET on point operations, allocates exactly what the hand-written loop allocates on 1000-row lists, and beats Dapper in every category on both time and allocations. The row type switches to SQLite''s natural provider types (long/double) because Dapper''s constructor mapping requires exact type matches and crashed on narrowing - noted in the docs as a fairness decision so all three contenders do identical work. The generated null guards cost 20% on list time versus raw; documented as the deliberate trade for descriptive NULL errors. Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
Dropping the prerelease suffix in the milestone''s final commit keeps the v0.2.0 tag and the package version it marks identical, per the versioning convention. Phase 3 (Verification) opens the 0.3.0-preview line with its first commit. Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
Restructured GitHub milestones so each phase gets one milestone (matching its minor version) instead of one per M-number, keeping all of a phase's PRs under a single milestone and making the milestone description a compounded summary of its M-numbers. Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Summary
Delivers M6 and closes Phase 2 (Codegen) at a clean
0.2.0: no new query features — this milestone proves the two claims the phase has been making.IsAotCompatibleon theSqlBoundruntime package turns on the trim/single-file/AOT analyzers (zero findings; withTreatWarningsAsErrorsany regression fails the build) and stamps the package metadata. A newaot-smoke-testCI job publishestest/SqlBound.AotSmokeTestwithPublishAotand executes the native binary — it exercises every generated shape (list, single, optional, scalar, scalar list, streaming, execute, property-mapped rows) plusSqlSessionagainst real SQLite, exit code as verdict.bench/SqlBound.Benchmarks(BenchmarkDotNet, convention recorded inarchitecture.md) compares SqlBound vs Dapper vs hand-written raw ADO.NET on identical SQL over in-memory SQLite across four categories, withMemoryDiagnoser. CI builds the project but never runs it; the baseline lives indocs/benchmarks.mdfrom a real local run:Directory.Build.propsshields BenchmarkDotNet''s generated host projects from the repo''s multi-targeting and warning escalation; benchmark method names share the tests'' async-suffix exemption since they label the result tables. The benchmark row type uses SQLite''s natural provider types (long/double) because Dapper''s constructor mapping requires exact type matches — documented as a fairness decision.PackageVersionto0.2.0, so thev0.2.0tag on the merge commit matches the package version exactly.Test plan
dotnet format --verify-no-changes; pack verified at0.2.0.aot-smoke-testCI job gets its first real exercise on this PR — the native publish + run is the check to watch.🤖 Generated with Claude Code