Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Use an IBufferWriter<byte> to write the outgoing SSPI blob #2452

Open
wants to merge 24 commits into
base: main
Choose a base branch
from

Conversation

twsouthwick
Copy link
Member

@twsouthwick twsouthwick commented Apr 8, 2024

This change removes the need to pre-allocate anything for the outgoing blobs of SSPI generation. As part of this:

  • An internal implementation of ArrayBufferWriter is added for platforms that do not support it
  • SqlObjectPool is imbued with the ability to create/reset pooled objects
  • TdsParser/TdsLogin is updated to use pooled ArrayBufferWriter instances to generate SSPI blobs
  • Native methods are updated to take in Span/* for writeable byte[]
  • SSPIContextProvider signature is updated to take IBufferWriter

Part of #2253

This change removes the need to pre-allocate anything for the outgoing blobs of SSPI generation. As part of this:

- An internal implementation of ArrayBufferWriter is added for platforms that do not support it
- SqlObjectPool is imbued with the ability to create/reset pooled objects
- TdsParser/TdsLogin is updated to use pooled ArrayBufferWriter instances to generate SSPI blobs
- Native methods are updated to take in Span/* for writeable byte[]
- SSPIContextProvider signature is updated to take IBufferWriter
@twsouthwick twsouthwick marked this pull request as ready for review May 7, 2024 21:20
@twsouthwick
Copy link
Member Author

@David-Engel can I get a review on this next step in the SSPI journey?

Copy link

codecov bot commented May 8, 2024

Codecov Report

Attention: Patch coverage is 78.35821% with 29 lines in your changes missing coverage. Please review.

Project coverage is 66.10%. Comparing base (081fc51) to head (c43f86f).

Files with missing lines Patch % Lines
.../src/Microsoft/Data/SqlClient/ArrayBufferWriter.cs 56.25% 21 Missing ⚠️
...c/Microsoft/Data/SqlClient/TdsParserStateObject.cs 85.41% 7 Missing ⚠️
...t/Data/SqlClient/SSPI/NativeSSPIContextProvider.cs 83.33% 1 Missing ⚠️

❗ There is a different number of reports uploaded between BASE (081fc51) and HEAD (c43f86f). Click for more details.

HEAD has 1 upload less than BASE
Flag BASE (081fc51) HEAD (c43f86f)
addons 1 0
Additional details and impacted files
@@            Coverage Diff             @@
##             main    #2452      +/-   ##
==========================================
- Coverage   72.73%   66.10%   -6.64%     
==========================================
  Files         283      278       -5     
  Lines       58997    58712     -285     
==========================================
- Hits        42910    38810    -4100     
- Misses      16087    19902    +3815     
Flag Coverage Δ
addons ?
netcore 69.21% <89.15%> (-6.33%) ⬇️
netfx 64.88% <77.51%> (-6.32%) ⬇️

Flags with carried forward coverage won't be shown. Click here to find out more.

☔ View full report in Codecov by Sentry.
📢 Have feedback on the report? Share it here.

@twsouthwick
Copy link
Member Author

@David-Engel ping

@David-Engel
Copy link
Contributor

I ran our internal Kerberos test pipeline against this PR and all tests passed.

@twsouthwick
Copy link
Member Author

@David-Engel David-Engel added this to the 6.0-preview1 milestone Jun 3, 2024
@twsouthwick
Copy link
Member Author

@David-Engel can you run this on the kerberos suite again?

@twsouthwick
Copy link
Member Author

@David-Engel something is up with the merges so let me get those fixed before you do the kerberos runs

@twsouthwick
Copy link
Member Author

@David-Engel I'm getting sporadic errors that don't seem to always repro: https://sqlclientdrivers.visualstudio.com/public/_build/results?buildId=96359&view=logs&j=b14281d2-3365-502e-c6c8-e9e46d660715&t=a67f9feb-8bad-50ac-92c7-d62292e3e6fb&l=63

Have you seen these or are they related to my pr?

@@ -8,6 +8,8 @@ namespace Microsoft.Data.SqlClient
{
internal partial class TdsParser
{
private static readonly SqlObjectPool<ArrayBufferWriter<byte>> _writers = new(20, () => new(), a => a.Clear());
Copy link
Contributor

Choose a reason for hiding this comment

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

No complain here only I'm curious about the constant 20 pooled objects here!
cc @David-Engel

Copy link
Member Author

Choose a reason for hiding this comment

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

honestly I don't remember where the 20 came from. Seemed reasonable I think at the time, but I'm not really aware of how many concurrent calls to it are called in a given connection

Copy link
Contributor

Choose a reason for hiding this comment

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

I dug into the SqlObjectPool logic because I was curious, so thought I would share in case anyone else was wondering. 20 here isn't a limit on parallelism or anything. It's just the maximum number that will be cached. Parallel Rents from the pool above 20 will simply get a new object. I agree that 20 should be plenty for the majority of scenarios.

Copy link
Contributor

Choose a reason for hiding this comment

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

Can you please add a comment in the code indicating the reasoning for 20?

@twsouthwick
Copy link
Member Author

@cheenamalhotra can you trigger a build again? will it automatically build if I switch it away from draft?

@twsouthwick twsouthwick marked this pull request as ready for review January 31, 2025 19:44
@twsouthwick
Copy link
Member Author

@David-Engel can you kick off the build for this?

@David-Engel
Copy link
Contributor

/azp run

Copy link

Azure Pipelines successfully started running 1 pipeline(s).

@twsouthwick
Copy link
Member Author

@David-Engel can you run the tests again?

@David-Engel
Copy link
Contributor

/azp run

Copy link

Azure Pipelines successfully started running 1 pipeline(s).

@twsouthwick
Copy link
Member Author

@David-Engel @cheenamalhotra This PR is passing all tests and ready for review. Thanks!

@@ -842,145 +842,6 @@ internal void WriteByte(byte b)
_outBuff[_outBytesUsed++] = b;
}

internal Task WriteByteSpan(ReadOnlySpan<byte> span, bool canAccumulate = true, TaskCompletionSource<object> completion = null)
Copy link
Member Author

Choose a reason for hiding this comment

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

Note: this is removed in the netcore/netfx specific files, and the netcore implementation is now in the shared TdsParserStateObject class

@paulmedynski paulmedynski requested review from a team and removed request for JRahnama and arellegue February 11, 2025 19:03
@twsouthwick
Copy link
Member Author

@David-Engel these build failures appear to be occurring on main as well. Can I get a review here?

@@ -8,6 +8,8 @@ namespace Microsoft.Data.SqlClient
{
internal partial class TdsParser
{
private static readonly SqlObjectPool<ArrayBufferWriter<byte>> _writers = new(20, () => new(), a => a.Clear());
Copy link
Contributor

Choose a reason for hiding this comment

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

I dug into the SqlObjectPool logic because I was curious, so thought I would share in case anyone else was wondering. 20 here isn't a limit on parallelism or anything. It's just the maximum number that will be cached. Parallel Rents from the pool above 20 will simply get a new object. I agree that 20 should be plenty for the majority of scenarios.

@mdaigle mdaigle requested a review from a team February 13, 2025 17:32
@twsouthwick
Copy link
Member Author

Looks like the "restore" step is failing for a bunch of the tests

@David-Engel
Copy link
Contributor

Looks like the "restore" step is failing for a bunch of the tests

Yup. It's not your PR. It seems like a new underlying tooling bug on ARM64. We are investigating.

}
try
{
TdsParser.ReliabilitySection.Assert("unreliable call to WriteByteArray"); // you need to setup for a thread abort somewhere before you call this method
Copy link
Contributor

Choose a reason for hiding this comment

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

@benrr101 FYI, you'll have a conflict on this line if you merge #3042 after this

@@ -8,6 +8,8 @@ namespace Microsoft.Data.SqlClient
{
internal partial class TdsParser
{
private static readonly SqlObjectPool<ArrayBufferWriter<byte>> _writers = new(20, () => new(), a => a.Clear());
Copy link
Contributor

Choose a reason for hiding this comment

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

Can you please add a comment in the code indicating the reasoning for 20?

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

Successfully merging this pull request may close these issues.

5 participants