Skip to content
This repository has been archived by the owner on Jan 23, 2023. It is now read-only.
/ corefx Public archive

Change SqlClient to use strongly typed packet and session handles #33155

Closed
wants to merge 7 commits into from

Conversation

Wraith2
Copy link
Contributor

@Wraith2 Wraith2 commented Oct 31, 2018

These changes remove constant boxing of session and packet handles which are IntPtr when using the native implementation of TdsParserStateObject (native is used in windows non-uap builds) which improves memory performance. Making these changes also allows assertion of the handle types in debug builds which adds safety and testability.

To do this I have had to add in a project DefineConstant called snidll to allow some fields to be omitted where the native implementation is not included, while I like the current configuration with extremely minimal #define usage I considered this and think the additional type safety offered is worth the new constant. I have also renamed a couple of types to clarify which types are used in which implementations.

The changes also include some changes to the ManualTests to add conditional facts on Udt and ServiceBroker reliant test cases so they won't run if the resources required aren't present or enabled. This assumes that a full test run with these available should not skip any tests. These changes were needed to allow me to run the manual tests locally without getting large numbers of errors to try and pick real problems out of.

please review, test, comment, say "oh no not this guy again" as usual 😁

/cc @keeratsingh @afsanehr @saurabh500 @David-Engel

rename SNIPacket to SNIPacketHandle
add PacketHandle type field and asserttions on native consumer methods
add SessionHandle strong type
@@ -98,14 +98,14 @@ public void Allocate(int capacity)
{
if (_isBufferFromArrayPool)
{
_arrayPool.Return(_data);
ArrayPool<byte>.Shared.Return(_data);
Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

If the default shared pool is being used it seems wasteful to carry around the extra field referring to it. The default pool can also be devirtualized by the jit possibly making the calls slightly faster.
I did wonder if it might be worth having an sql specific pool for packet buffers but considered the advice warning of creating too many pools and decided to err on the side of caution.

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

The default pool can also be devirtualized by the jit possibly making the calls slightly faster.

Yep, when referred to directly via ArrayPool<byte>.Shared dotnet/coreclr#20637

@Wraith2 Wraith2 changed the title [WIP] Change SqlClient to use strongly typed packet and session handles Change SqlClient to use strongly typed packet and session handles Oct 31, 2018
@saurabh500
Copy link
Contributor

oh no not this guy again !!! 😄
Thanks for the changes and improving SqlClient. We will review the changes soon.

@saurabh500
Copy link
Contributor

Do you have any measurements for the impact of these changes?

@Wraith2
Copy link
Contributor Author

Wraith2 commented Oct 31, 2018

I haven't done any direct measurements because these changes are on a different branch to my other perf changes in #32811. While I was working on the other PR I got to the point where the allocations were all putting values into objects in the parameters (unavoidable) and the IntPtr boxing for the various methods changed here. So logically it should roughly half the GC frequency seen in the graphs posted on the other PR.

Now there are deeper concerns. I'm changing an object which is a single reference in size to a struct 4 times the size which is going to have some impact. When I looked at the uses of the new types all of them were used with a small number of other parameters so while there is more data present now there should be enough registers to allow them to be passed quickly or by reference. Doing some microbenching I could try to identify if it is faster to force references with `in' modifiers but realistically the cpu time is spent waiting on sql server and going to that low level is over optimising at this time.

In performance terms it will be a memory net win. It may have a small throughput degredation but that is likely to be balanced by the lack of boxing instructions and memory operations related to it, it might even be a net win on that side.

@Wraith2
Copy link
Contributor Author

Wraith2 commented Nov 1, 2018

Ok, got some profile results (still can't get BDN to co-operate) they show that there is a minor improvement in both memory and speed. This is a slightly improved version of the benchmark written for
#32811 where I've removed some overhead from the benchmark setup and stopped using prepared statements. The results are only comparable to each other not between PR's. 100x1000 float inserts.

Before:
before

After:
after

Less GC peaks and probably because of that ~13% faster.

@Wraith2
Copy link
Contributor Author

Wraith2 commented Nov 8, 2018

@dotnet-bot Test Linux x64 Release Build

@Wraith2
Copy link
Contributor Author

Wraith2 commented Nov 16, 2018

EFCore tests passed on this change.

@Wraith2
Copy link
Contributor Author

Wraith2 commented Nov 19, 2018

Nudge.

@benaadams
Copy link
Member

@dotnet-bot test Windows x64 Debug Build

@Wraith2
Copy link
Contributor Author

Wraith2 commented Dec 12, 2018

For easier review and merging I have split this into #34040 and #34044.

@Wraith2 Wraith2 closed this Dec 12, 2018
@Wraith2 Wraith2 deleted the sqlpacket branch December 15, 2018 11:33
@karelz karelz added this to the 3.0 milestone Dec 21, 2018
Sign up for free to subscribe to this conversation on GitHub. Already have an account? Sign in.
Projects
None yet
Development

Successfully merging this pull request may close these issues.

7 participants