Repository navigation
Releases: sanamhub/ada-csharp
Release list
v0.1.1
Added
- Published benchmark results for 0.1.0, in
docs/benchmarks/0.1.0/, covering the five platforms
with a hosted runner. Every native in the run was a cache hit whose sha256 matches
native/CHECKSUMS.txt, so the numbers describe the released bytes rather than a rebuild.
Windows arm64 is measured for the first time. The export list and/GLchange from ADR-0006
shows up as 10 percent on W2, flat on Linux over the same pair of runs, which is the control
that makes it attributable. W1 improved on Windows too, but improved further on Linux with no
build change, so the page credits that to the runner rather than to the optimisation. linux-musl-arm64. Alpine on arm64 got aDllNotFoundExceptionfor a reason that had nothing
to do with the caller's code. Built by the existingbuild-musl.shon an arm64 runner, and the
consumption test runs in an Alpine container on arm64, so the library is loaded on the platform
it targets rather than assumed to work because it compiled. ADR-0009.SECURITY.mdadded, pointing vulnerability reports at private GitHub security advisories.
Changed
- README rewritten as a short consumer page. Its links are absolute, because the README ships in
the package and relative links were broken on nuget.org. Benchmark detail moved to
docs/performance.md. - Windows natives build without
/GLand/LTCG, so both Windows binaries are byte identical
across runner images andnative/CHECKSUMS.txtgates them again. With them on, MSVC produced
different bytes on different images from identical sources and component versions, and a
release had roughly a coin flip per Windows RID of failing its checksum step for an innocent
reason. Costs 4 to 13 percent onCanParseand 3 to 5 percent on a hard URL.CanParsestays
well ahead ofUri.TryCreate. The generated export list stays. ADR-0011, #45. native/build-windows.ps1takes-Ipo on|off, defaultoff.onexists so the comparison can
be rerun.all-symbolswith/GLis refused up front, since it dies incmake -E __create_def
on IL objects.win-perf-experiment.ymlgains variantc, a pure/GLcomparison, and a RID input so
win-arm64can be measured onwindows-11-arm. Variantamoves exports and/GLtogether,
so #18's 7 percent covers the pair rather than/GLalone.
Fixed
scripts/collate-benchmarks.pyno longer drops a platform without saying so. Its platform list
is hand maintained,win-arm64was added tobench.ymland not to it, and the result was a
green run and a summary that simply had no Windows arm64 column. It now fails when a
benchmark-<rid>artifact arrives for a RID it does not know.scripts/collate-benchmarks.pyno longer labels a measured row as the baseline of its group.
It read the baseline offRatiobeing1.00, which a row that lands within half a percent of
the baseline also prints. Two real Windows x64 rows in this run did exactly that, 158.90 ns
against 158.15 ns.Program.csnow asks BenchmarkDotNet for itsBaselinecolumn, and the
script prefers it, falling back toRatioonly where a single row in the group claims1.00.- The Alpine image was pinned to an amd64 image digest rather than to the multi-architecture
index. On an arm64 host docker either refuses that or runs it under emulation and produces an
x86-64.soin thelinux-musl-arm64directory. The pin is now the 3.20.0 index, which
resolves per host and keeps both musl RIDs on one Alpine release. The amd64 image inside it is
the one the old pin named, solinux-musl-x64is byte for byte unchanged. native/build-musl.shhands ownership of what it built back to the invoking user. The
container runs as root, so everything it wrote into the bind mount was root owned and the
runner user could not delete it. The reproducibility check does exactly that between its two
builds and failed withPermission deniedon every file the first build produced.apkneeds
root, so ownership is handed back on the way out rather than dropped on the way in.native/verify-unix.shchecks the ELF machine type against the RID instead of trusting the
runner. A container built for one platform, or a QEMU binfmt handler doing its job quietly,
produces a library for the wrong architecture that passes exports, hardening and checksums, and
then fails on exactly the machines the RID exists for. ADR-0008 added the PE half of this for
win-arm64.
Install
dotnet add package Ada.Url --version 0.1.1
Verification
- Attached: the package, its symbols, and a CycloneDX SBOM listing the native library.
- The eight native binaries are built from the pinned Ada tag in CI and their SHA-256
checksums are matched againstnative/CHECKSUMS.txtbefore the package is pushed. - Published with NuGet trusted publishing, so no long lived API key exists for this repository.
v0.1.0
Out of beta. Nothing in the API changed to earn that: the surface has been stable since
0.1.0-beta.1 and moves to PublicAPI.Shipped.txt unchanged. What changed is that the questions
the beta was holding open have answers.
0.1.0-beta.1 said beta because the API "may still move". It has not, through two betas. The
Windows performance gap was the other open question and it is measured now, in ADR-0006 and
ADR-0007, rather than explained by a guess this file used to print as fact.
This is still 0.x. Under SemVer that means a minor bump may break the API, so the promise here
is that the surface is considered done, not that it is frozen.
Added
-
win-arm64. Native binaries for it ship in the package, the conformance suite runs on a
windows-11-armrunner, and the reproducibility check and the checksum manifest cover it. The
binary cross compiles from the x64 runner, sonative/verify-windows.ps1now reads the PE
machine field and fails unless it matches the RID: an x64 binary shipped underwin-arm64
would pass every other gate and then fail on exactly the machines the RID exists for.
/CETCOMPATis not passed there, because CET is x86 and x64 only and the linker takes the flag
and emits nothing. ADR-0008. -
Benchmark
W4gainedReuseHandleAndReadHostname, which re-parses into oneAdaUrlthrough
TrySetHrefinstead of allocating a URL object per URL. It is the only lever the binding has
over the native allocation and it is worth the most on Windows. -
native/bench/alloc-probe.cppand a dispatch only workflow that runs it on Windows and Linux.
It replaces globaloperator newto count and size whatada_parseallocates, then times
ada_can_parse,ada_parsewithada_free, a replay of just the recorded allocations, and
ada_set_hrefon a kept handle, reporting each against the allocation free control because the
two runners are different machines.
Changed
- README says why Windows is slower instead of listing hypotheses, and documents handle reuse
with the case where it does not help. The Windows gap is the heap:ada_parseallocates twice
per URL and replaying those two allocations alone costs 87 ns on Windows against 22 ns on
Linux, which is 76% of everything the Windows parse spends beyond validating. Reproduced in two
runs, decided in ADR-0007, measured in #20. - The claim that the native allocation is "an upstream limit rather than something this package
can route around" was half wrong and is corrected.ada_set_hrefre-parses into an existing
handle, so a loop can avoid one of the two allocations. Worth 27% on Windows and 8% on Linux
on a plain URL, and nothing at all on a hard one.
Removed
- The clang-cl toolset option in
native/build-windows.ps1,native/cmake/clang-cl-tweaks.cmake,
the toolset probe workflow, and the two clang-cl variants in the performance experiment. It
existed to answer #19, whether a different code generator closes the Windows gap. ADR-0007
answered that from the other direction: the gap is the heap, and both compilers link against
the same one. The path also carried a build flag that never worked,/p:UseLldLink=false,
which is worse to leave in than to remove.
Fixed
- The ADR-0001 gate stopped reading generated code. It greps
srcandtestsfor#ifand runs
after the build, so it was walkingobjtoo. xunit.v3 4.0.1 added an
#if XUNIT_GENERATED_DISABLE_WARNINGSguard to its generated test entry point and failed a gate
about source on a dependency bump that touched none.
Install
dotnet add package Ada.Url --version 0.1.0
Verification
- Attached: the package, its symbols, and a CycloneDX SBOM listing the native library.
- The seven native binaries are built from the pinned Ada tag in CI and their SHA-256
checksums are matched againstnative/CHECKSUMS.txtbefore the package is pushed. - Published with NuGet trusted publishing, so no long lived API key exists for this repository.
v0.1.0-beta.2
Still beta. No public API changed in this release: it is a faster and much smaller Windows
binary, a hardening gate that was not actually gating, and a performance section that now says
what the measurements support rather than what was assumed.
Added
- Benchmark
W4, which measures the gap between validating a URL and parsing one. About two
thirds of a parse isada_parseallocating a URL object andada_freereleasing it, so the
gap is now tracked rather than rediscovered.
Changed
- README performance section reports sustained throughput and per platform speedups alongside
the existing per call figures. The headline said "roughly twice as fast asSystem.Uri", which
came from a single URL microbenchmark with a hot cache on one platform. A full parse is 1.9x
on Linux x64 and level on Windows x64, and allocation is zero everywhere. - README performance section is a third shorter, down from eight subsections to five, and the
comparison column now reads as a speedup, 1.9x, rather than a ratio below one, 0.52x, which is
easy to read backwards. The per platform table no longer has a column whose every cell said
"see below". docs/benchmarks/0.1.0-beta.1/holds results for all four platforms. The alpha results are
kept and marked superseded.- The win-x64 native library is built with whole program optimisation, behind an export list
generated from upstream'sinclude/ada_c.h.ada.dlldrops from 487,936 bytes to 279,552,
43% smaller, and a hard URL parses about 7% faster. Both changed at once, so that 7% belongs to
the pair and not to either half. A plain URL does not move measurably. The
exported surface narrows from every mangled C++ symbol in the library to the 79 functions the
C API declares, which is a breaking change only for something linking against Ada's internals
directly: this package imports 79 entry points and the header declares exactly 79. Measured
over three rotated rounds in #18, decided in ADR-0006. - The test suite runs on Microsoft.Testing.Platform. xunit.v3 4.0.0 ships on MTP v2, which no
longer bridges to VSTest on the .NET 10 SDK, soglobal.jsonselects the MTP runner and the
VSTest host, adapter and collector are gone. Coverage now comes from
Microsoft.Testing.Extensions.CodeCoverage and the TRX report from
Microsoft.Testing.Extensions.TrxReport. Every workflow filters with
--filter-traitrather than--filter. All 1,253 tests pass unchanged.
Fixed
- Benchmark
W1comparedCanParseagainstnew Uri()plus reading three components, which is
not the same work, and the README repeated the result as "about 4x faster to validate". Against
the cheapest equivalent,Uri.TryCreatediscarded, validation is about 1.3x faster on a plain
URL and slightly slower on a corpus heavy in internationalised hosts.CanParsenow has its
own category,W0 validate, with a like for like baseline, and the README says what the
measurements support. - The benchmark collation produced a summary with no comparison in it. Every ratio printed as
n/aand every benchmark was grouped under a heading called "other", because the script read
BenchmarkDotNet's JSON export, which carries neither aCategoriesfield nor a baseline
marker. It now reads the markdown export, which has both, and fails loudly if no row ends up
with a ratio. - The nuget.org page had no project website link.
PackageProjectUrlwas never set.
Security
- The win-x64 hardening gate checks CET instead of assuming it.
/CETCOMPATis recorded in the
PE debug directory rather than inDllCharacteristics, sonative/verify-windows.ps1read
four bits and took the fifth on trust. A toolchain that accepts the flag and emits no record
would have shipped a binary with no shadow stack support, and nothing would have said so. The
check is skipped on machines that are not x64, where/CETCOMPAThas no equivalent.
Known
-
Windows is level with
System.Uriwhere Linux is 1.9x ahead, and the cause is now narrowed to
allocation. Whole program optimisation was the standing answer and it is the wrong one: the
generated export list and/GLtogether are worth about 7% on a hard URL, not the factor of
two this file used to claim without measuring, and the two changed together so neither can take
the credit alone.What the benchmarks actually say is that Ada's non-allocating work is not slow on Windows at
all.CanParsecosts 40.9 ns there against 47.0 ns on Linux. The whole divergence is in the
step from validating to parsing, which is whereada_parseallocates a result object and the
std::stringbuffer inside it: 95.3 ns on Windows against 43.2 ns on Linux, 2.2x, and 2.8x
once normalised against the same machine's managed baseline.That points at the allocator rather than the code generator, so #20 is the live question and
#19 is much less promising than it looked. Tracked in #20.
Install
dotnet add package Ada.Url --version 0.1.0-beta.2
Verification
- Attached: the package, its symbols, and a CycloneDX SBOM listing the native library.
- The six native binaries are built from the pinned Ada tag in CI and their SHA-256
checksums are matched againstnative/CHECKSUMS.txtbefore the package is pushed. - Published with NuGet trusted publishing, so no long lived API key exists for this repository.
v0.1.0-beta.1
First published release. Beta rather than alpha because the WHATWG conformance suite passes in
full on four platforms and the package is verified by installing it into a clean project, but
the public API has had no outside use yet and may still move.
Added
- Engineering plan (
docs/ADA_PLAN.md) covering framework targeting, native build,
P/Invoke architecture, conformance testing, benchmarks, and CI. - Repository scaffold: solution, library and test projects on
net10.0, central package
management, analyzer and lint gates,ci.yml, and ADR-0001 through ADR-0005. - Native build for all six RIDs: build scripts for Windows, Linux, Alpine, and macOS, plus
native.ymlwith export, hardening, and checksum gates. - Interop layer: the full
ada_c.hsurface bound withLibraryImport, blittable ABI structs,
a native resolver for single file and development layouts, and allocation free UTF-16
transcoding. - Public API:
AdaUrlfor multi property work, one shot statics for validation and
normalisation,AdaUrlComponents, andAdaLibrary. - Tests: ABI conformance, parsing behaviour, and allocation assertions.
- WHATWG conformance suite over the vendored web-platform-tests corpus, pinned at a known
commit: 874 parse cases and 278 setter cases. AdaSearchParamswith an allocation free struct enumerator, andAdaIdnafor UTS-46
conversion.
Notes
- Conformance is verified on Linux x64, Linux arm64, macOS arm64, and Windows x64.
Install
dotnet add package Ada.Url --version 0.1.0-beta.1
Verification
- Attached: the package, its symbols, and a CycloneDX SBOM listing the native library.
- The six native binaries are built from the pinned Ada tag in CI and their SHA-256
checksums are matched againstnative/CHECKSUMS.txtbefore the package is pushed. - Published with NuGet trusted publishing, so no long lived API key exists for this repository.