32KB TDS packets for monitored-server connections — the first #2164 lever, measured - #2178
Conversation
Neither app set PacketSize, so every connection ran at the driver's 8KB default. The open/drain split showed drain is 94-97% of a query_store pass, and that drain throughput tracks LOB SIZE rather than total bytes: ~180KB/row moved 256 KB/s while ~41KB/row moved 1,080 KB/s over the same link, same code, same budget. That inverse relationship is per-packet overhead — a 180KB plan costs ~22 packets at 8KB and ~6 at 32KB. One shared constant in Common so the two independent builders cannot drift. 32KB is the protocol maximum and both ends negotiate down, so a server that dislikes it degrades rather than failing. This is a measurement, not a conclusion: the before numbers are on #2164 and I'll post the after from the same databases. If it doesn't move, it comes out. Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
|
Reviewed the diff (CHANGELOG, Parity — Both builders set
Correctness — The one thing worth independently verifying was whether Minor, non-blocking nit: the doc comment on No missing-index-DMV comments, per instructions. |
The measurement that motivated this
The open/drain instrumentation (#2173) shipped and overturned my prior conclusion. Seven samples, three servers, 12MB budget:
Two facts fall out:
That inverse relationship is per-packet overhead. Nothing in either app set
PacketSize, so every connection ran at the driver's 8 KB default — a 180 KB plan costs ~22 packets where 32 KB packets cost ~6.The change
One shared constant in
PerformanceMonitor.Commonapplied by both builders (MonitoredServerConnection.BuildConnectionStringfor Darling,ServerConnection.BuildConnectionStringfor Lite), because the two are otherwise independent code and this is exactly the kind of setting that drifts silently.32 KB is the protocol maximum; the driver accepts 512–32768 and both ends negotiate down to the smaller, so a server that dislikes it degrades rather than failing. The cost of being wrong is per-connection network buffer memory on both ends — kilobytes at our connection count, which is why it's a constant rather than a knob until someone shows it hurts.
This is a measurement, not a conclusion
The before numbers are above. I'll post the after from the same databases once this is on the dogfood fleet. If it doesn't move the drain, it comes back out — and the next lever is
CommandBehavior.SequentialAccess(also unused today), then the known-hash plan skip, which the LOB-transfer finding puts back on the table for a better reason than the one I originally had.Testing
PacketSizeTuningTestspins that Darling's builder actually emits it (the setting is invisible at runtime — a wrong packet size behaves correctly and merely runs slowly, so only a pin notices it being dropped), that the value stays inside the driver's accepted range (outside it throws at connect time, which on a monitoring fleet means every server going dark at once — that bound matters more than the tuning), and that it isn't silently reverted to the 8 KB default. Common, Darling service, Lite, and Darling.Tests build clean.Part of #2164.
(Database names are relabelled
db-*— this repo is public and the originals are client-identifying. Server names and every measurement are unchanged.)