-
Notifications
You must be signed in to change notification settings - Fork 10.4k
Allow use of a default MemoryPoolFeature on ConnectionContext #18579
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
Conversation
@@ -33,7 +34,7 @@ public Task OnConnectionAsync(ConnectionContext connectionContext) | |||
Protocols = _protocols, | |||
ServiceContext = _serviceContext, | |||
ConnectionFeatures = connectionContext.Features, | |||
MemoryPool = memoryPoolFeature.MemoryPool, | |||
MemoryPool = memoryPoolFeature?.MemoryPool ?? System.Buffers.MemoryPool<byte>.Shared, |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
We should let this be null (without the null ref that is). Don't fallback to the default memory pool though. If that breaks we should fix those places that use the pool directly.
We also need to add a test for this to make sure it doesn't break.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I see what you mean. So leave it as
memoryPool = memoryPoolFeature?.MemoryPool
and solve any side-effects later on in the code path where they occur ?
This could be tested with MemoryEndPoint.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Yep.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Isn't the MemoryPoolFeature accessible in any middleware wired up to Ketsrel through the HttpConnectionContext ? If so, any middleware assuming it's presence will break when the endpoint in the instance of Kestrel is changed to a non-socket based endpoint like MemoryEndPoint.
Consider the scenario where my kestrel based app,, is switching to MemoryEndpoint for testing purposes and at the same time I am retrieving the MemoryPoolFeature in my middleware making use of it.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Yes but this isn't a required feature so I'd like to understand the places that rely on it being non-null.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Why not include ?? MemoryPool<byte>.Shared
here? The same thing will happen implicitly later when we new up PipeOptions.
Yes but this isn't a required feature so I'd like to understand the places that rely on it being non-null.
By adding ?? MemoryPool<byte>.Shared
, the middleware is no longer relying on the feature.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
What middleware is that? This is a specific middleware (the HTTP middleware) that relies on it currently. The TLS middleware already handles this.
Before doing this fix I just want to understand what code in the HTTP layer relies on this being non-null. I have no problem putting it back.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
What's the point? Like you say, this is the HTTP middleware. By adding this, there would be no code in the HTTP layer that relies on this being non-null.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I just want to understand what code in the HTTP layer relies on this being non-null
I have no problem putting it back
Would I be right in thinking that these two actions are independent and that one is not a blocker for the other ? I guess the first can be achieved by setting the MemoryPool to null and seeing where the Tests fail ( I did this and there were at least 13 failures)
and the second can be done to introduce the fix but without any significant hindrance to carrying out the first (given the change is trivial) ?
if on the other hand :
I just want to understand what code in the HTTP layer relies on this being non-null
is likely to lead to a different outcome then that's a different matter.
A bit of context (no pun intended), the MemoryPool was set in the ConnectionContext when binding to a socket but was not set in the ConnectionContext when binding to a (Bedrock) MemoryEndpoint. In both cases ConnectionContext was intended to pushed down the HttpMiddleware.
Is the Transport factory obliged to set the MemoryPool ? If so, how could it be enforced ? If not then I guess provision of a fallback default is mandatory and why is it set in the ConnectionContext in kestrel ?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
What's the point? Like you say, this is the HTTP middleware. By adding this, there would be no code in the HTTP layer that relies on this being non-null.
The transport isn't required to set a pool and the IMemoryPoolFeature isn't required. Kestrel needs to take that into account. Kestrel can also polyfill by defaulting to using a pool but I have 2 concerns:
- We don't have an understanding where it does that. I'd like to understand before making assumptions.
- We probably want to use the SlabMemoryPool and not the default memory pool in the places where we explicitly allocate.
Would I be right in thinking that these two actions are independent and that one is not a blocker for the other ? I guess the first can be achieved by setting the MemoryPool to null and seeing where the Tests fail ( I did this and there were at least 13 failures)
and the second can be done to introduce the fix but without any significant hindrance to carrying out the first (given the change is trivial) ?
The code change is trivial, measuring the impact isn't without understanding what parts of the code rely on this instance.
Is the Transport factory obliged to set the MemoryPool ? If so, how could it be enforced ? If not then I guess provision of a fallback default is mandatory and why is it set in the ConnectionContext in kestrel ?
Features can be optional, it's part of the system. It's not set on the ConnectionContext, it's just an optional feature that middleware may use if it exists.
@@ -43,5 +44,6 @@ public Task OnConnectionAsync(ConnectionContext connectionContext) | |||
|
|||
return connection.ProcessRequestsAsync(_application); | |||
} | |||
|
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Nit: remove this empty line.
Sounds like we're waiting for author feedback on the proposal to continue to let the memory pool be null but change our consumption points to use a default. Correct? Trying to identify what we need to do to get this PR resolved/closed. |
I will try this weekend to figure out where the memorypool is being used. |
@davidfowl Do you still want this? |
Yes. |
@davidfowl Are you fine with this as is? |
At this point the only change I would make is to use the SlabPool. |
I think that makes more sense. I figured that given a transport that doesn't implement the IMemoryPoolFeature, we don't care about using the most optimal pool. But then again, why not? We can just change Edit: SlabMemoryPool is shared source, so we'll also need to add |
Looking at this more, I think changing to use the SlabMemoryPool in Kestrel.Core will be very difficult. There are a bunch of test projects that have InternalsVisibleTo access to both Kestrel.Core internals and the internals to one of the transports that also use the SlabMemoryPool as shared source. This means adding the SlabMemoryPool to Kestrel.Core causes a bunch of type conflicts 😢 |
After more discussion with @davidfowl, it looks like we're taking this as is 😄 |
…set on ConnectionContext This facilitates the use of other Transports other than sockets. When kestrel bound to MemoryTransport (Bedrock davidfowl/BedrockFramework#65) a NullReferenceException is thrown since the MemoryPoolFeature is not set on the ConnectionContext set in that Transport
@dotnet/dnceng Is the CLA necessary for such a small change? I don't know why the bot is only triggering now. |
Thanks @Ninds! |
davidfowl/BedrockFramework#65
This facilitates the use of other Transports other than sockets.
When kestrel bound to MemoryTransport (Bedrock davidfowl/BedrockFramework#65) a NullReferenceException is thrown since the MemoryPoolFeature is not set on the ConnectionContext set in that Transport
Summary of the changes (Less than 80 chars)
Addresses #bugnumber (in this specific format)