-
Notifications
You must be signed in to change notification settings - Fork 10.5k
Add ISocketConnectionContextFactory #34769
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
Merged
Merged
Changes from all commits
Commits
Show all changes
32 commits
Select commit
Hold shift + click to select a range
f27d98e
Initial surgery
HaoK 18a1c7e
Update SocketConnectionListener.cs
HaoK 259abf4
Try to fix shutdown tests
HaoK 5181891
Fix bind tests
HaoK e355dc5
Update SocketConnectionListener.cs
HaoK 9bfb037
Fix lifetime issues with internal properties
HaoK 239fe90
Update WebHostBuilderSocketExtensions.cs
HaoK 2dc98ef
Make context factory public and fix UseKestrel
HaoK cc1328b
Fix DelaySocketOperations to match NoDelay defaults
HaoK 06116eb
Don't access socket.NoDelay cuz unix sockets
HaoK fde7a12
Remove debugging
HaoK 7868f4a
CR feeedback
HaoK 2e98b46
Cleanup
HaoK 93ab48b
Fix test
HaoK 6da8c40
Remove interface
HaoK bc57055
Initial surgery
HaoK 4fff4d3
Make context factory public and fix UseKestrel
HaoK 52c8d11
Remove interface
HaoK 26cba39
Updates
HaoK 66b244b
Update to new API
HaoK 3f4e88b
Undo
HaoK e03c29c
Revert
HaoK c327e9c
Undo submodule update
HaoK 218fae6
Undo api changes
HaoK 776ad32
Update PublicAPI.Shipped.txt
HaoK 401322f
Remove DeferFirstOperation
HaoK 407c2c5
Start connection in Create
HaoK 7399f8b
Move sender pool queues into Factory
HaoK 0ae6a82
Cleanup
HaoK e0494d2
Rename field
HaoK b60a92f
CR feedback
HaoK ebbca3d
Fix test
HaoK File filter
Filter by extension
Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
There are no files selected for viewing
3 changes: 0 additions & 3 deletions
3
src/Servers/Kestrel/Transport.Sockets/src/Internal/SocketConnection.cs
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
132 changes: 132 additions & 0 deletions
132
src/Servers/Kestrel/Transport.Sockets/src/SocketConnectionContextFactory.cs
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,132 @@ | ||
| // Licensed to the .NET Foundation under one or more agreements. | ||
| // The .NET Foundation licenses this file to you under the MIT license. | ||
|
|
||
| using System.Buffers; | ||
| using System.IO.Pipelines; | ||
| using System.Net.Sockets; | ||
| using Microsoft.AspNetCore.Connections; | ||
| using Microsoft.AspNetCore.Server.Kestrel.Transport.Sockets.Internal; | ||
| using Microsoft.Extensions.Logging; | ||
|
|
||
| namespace Microsoft.AspNetCore.Server.Kestrel.Transport.Sockets | ||
| { | ||
| /// <summary> | ||
| /// A factory for socket based connections contexts. | ||
| /// </summary> | ||
| public sealed class SocketConnectionContextFactory : IDisposable | ||
| { | ||
| private readonly MemoryPool<byte> _memoryPool; | ||
| private readonly SocketConnectionFactoryOptions _options; | ||
| private readonly ISocketsTrace _trace; | ||
| private readonly int _settingsCount; | ||
| private readonly QueueSettings[] _settings; | ||
| private int _settingsIndex; | ||
|
|
||
| /// <summary> | ||
| /// Creates the <see cref="SocketConnectionContextFactory"/>. | ||
| /// </summary> | ||
| /// <param name="options">The options.</param> | ||
| /// <param name="logger">The logger.</param> | ||
| public SocketConnectionContextFactory(SocketConnectionFactoryOptions options, ILogger logger) | ||
| { | ||
| if (options == null) | ||
| { | ||
| throw new ArgumentNullException(nameof(options)); | ||
| } | ||
|
|
||
| if (logger == null) | ||
| { | ||
| throw new ArgumentNullException(nameof(logger)); | ||
| } | ||
|
|
||
| _options = options; | ||
| _trace = new SocketsTrace(logger); | ||
| _memoryPool = _options.MemoryPoolFactory(); | ||
| _settingsCount = _options.IOQueueCount; | ||
|
|
||
| var maxReadBufferSize = _options.MaxReadBufferSize ?? 0; | ||
| var maxWriteBufferSize = _options.MaxWriteBufferSize ?? 0; | ||
| var applicationScheduler = options.UnsafePreferInlineScheduling ? PipeScheduler.Inline : PipeScheduler.ThreadPool; | ||
|
|
||
| if (_settingsCount > 0) | ||
| { | ||
| _settings = new QueueSettings[_settingsCount]; | ||
|
|
||
| for (var i = 0; i < _settingsCount; i++) | ||
| { | ||
| var transportScheduler = options.UnsafePreferInlineScheduling ? PipeScheduler.Inline : new IOQueue(); | ||
| // https://github.com/aspnet/KestrelHttpServer/issues/2573 | ||
| var awaiterScheduler = OperatingSystem.IsWindows() ? transportScheduler : PipeScheduler.Inline; | ||
|
|
||
| _settings[i] = new QueueSettings() | ||
| { | ||
| Scheduler = transportScheduler, | ||
| InputOptions = new PipeOptions(_memoryPool, applicationScheduler, transportScheduler, maxReadBufferSize, maxReadBufferSize / 2, useSynchronizationContext: false), | ||
| OutputOptions = new PipeOptions(_memoryPool, transportScheduler, applicationScheduler, maxWriteBufferSize, maxWriteBufferSize / 2, useSynchronizationContext: false), | ||
| SocketSenderPool = new SocketSenderPool(awaiterScheduler) | ||
| }; | ||
| } | ||
| } | ||
| else | ||
| { | ||
| var transportScheduler = options.UnsafePreferInlineScheduling ? PipeScheduler.Inline : PipeScheduler.ThreadPool; | ||
| // https://github.com/aspnet/KestrelHttpServer/issues/2573 | ||
| var awaiterScheduler = OperatingSystem.IsWindows() ? transportScheduler : PipeScheduler.Inline; | ||
| _settings = new QueueSettings[] | ||
| { | ||
| new QueueSettings() | ||
| { | ||
| Scheduler = transportScheduler, | ||
| InputOptions = new PipeOptions(_memoryPool, applicationScheduler, transportScheduler, maxReadBufferSize, maxReadBufferSize / 2, useSynchronizationContext: false), | ||
| OutputOptions = new PipeOptions(_memoryPool, transportScheduler, applicationScheduler, maxWriteBufferSize, maxWriteBufferSize / 2, useSynchronizationContext: false), | ||
| SocketSenderPool = new SocketSenderPool(awaiterScheduler) | ||
| } | ||
| }; | ||
| _settingsCount = 1; | ||
| } | ||
| } | ||
|
|
||
| /// <summary> | ||
| /// Create a <see cref="ConnectionContext"/> for a socket. | ||
| /// </summary> | ||
| /// <param name="socket">The socket for the connection.</param> | ||
| /// <returns></returns> | ||
| public ConnectionContext Create(Socket socket) | ||
| { | ||
| var setting = _settings[Interlocked.Increment(ref _settingsIndex) % _settingsCount]; | ||
|
|
||
| var connection = new SocketConnection(socket, | ||
| _memoryPool, | ||
| setting.Scheduler, | ||
| _trace, | ||
| setting.SocketSenderPool, | ||
| setting.InputOptions, | ||
| setting.OutputOptions, | ||
| waitForData: _options.WaitForDataBeforeAllocatingBuffer); | ||
|
|
||
| connection.Start(); | ||
| return connection; | ||
| } | ||
|
|
||
| /// <inheritdoc /> | ||
| public void Dispose() | ||
| { | ||
| // Dispose the memory pool | ||
| _memoryPool.Dispose(); | ||
|
|
||
| // Dispose any pooled senders | ||
| foreach (var setting in _settings) | ||
| { | ||
| setting.SocketSenderPool.Dispose(); | ||
| } | ||
| } | ||
|
|
||
| private class QueueSettings | ||
| { | ||
| public PipeScheduler Scheduler { get; init; } = default!; | ||
| public PipeOptions InputOptions { get; init; } = default!; | ||
| public PipeOptions OutputOptions { get; init; } = default!; | ||
| public SocketSenderPool SocketSenderPool { get; init; } = default!; | ||
| } | ||
| } | ||
| } |
68 changes: 68 additions & 0 deletions
68
src/Servers/Kestrel/Transport.Sockets/src/SocketConnectionFactoryOptions.cs
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,68 @@ | ||
| // Licensed to the .NET Foundation under one or more agreements. | ||
| // The .NET Foundation licenses this file to you under the MIT license. | ||
|
|
||
| using System.Buffers; | ||
|
|
||
| namespace Microsoft.AspNetCore.Server.Kestrel.Transport.Sockets | ||
| { | ||
| /// <summary> | ||
| /// Options for <see cref="SocketConnectionContextFactory"/>. | ||
| /// </summary> | ||
| public class SocketConnectionFactoryOptions | ||
| { | ||
| /// <summary> | ||
| /// Create a new instance. | ||
| /// </summary> | ||
| public SocketConnectionFactoryOptions() { } | ||
|
|
||
| internal SocketConnectionFactoryOptions(SocketTransportOptions transportOptions) | ||
| { | ||
| IOQueueCount = transportOptions.IOQueueCount; | ||
| WaitForDataBeforeAllocatingBuffer = transportOptions.WaitForDataBeforeAllocatingBuffer; | ||
| MaxReadBufferSize = transportOptions.MaxReadBufferSize; | ||
| MaxWriteBufferSize = transportOptions.MaxWriteBufferSize; | ||
| UnsafePreferInlineScheduling = transportOptions.UnsafePreferInlineScheduling; | ||
| MemoryPoolFactory = transportOptions.MemoryPoolFactory; | ||
| } | ||
|
|
||
| /// <summary> | ||
| /// The number of I/O queues used to process requests. Set to 0 to directly schedule I/O to the ThreadPool. | ||
| /// </summary> | ||
| /// <remarks> | ||
| /// Defaults to <see cref="Environment.ProcessorCount" /> rounded down and clamped between 1 and 16. | ||
| /// </remarks> | ||
| public int IOQueueCount { get; set; } = Math.Min(Environment.ProcessorCount, 16); | ||
|
|
||
| /// <summary> | ||
| /// Wait until there is data available to allocate a buffer. Setting this to false can increase throughput at the cost of increased memory usage. | ||
| /// </summary> | ||
| /// <remarks> | ||
| /// Defaults to true. | ||
| /// </remarks> | ||
| public bool WaitForDataBeforeAllocatingBuffer { get; set; } = true; | ||
|
|
||
| /// <summary> | ||
| /// Gets or sets the maximum unconsumed incoming bytes the transport will buffer. | ||
| /// </summary> | ||
| public long? MaxReadBufferSize { get; set; } = 1024 * 1024; | ||
|
|
||
| /// <summary> | ||
| /// Gets or sets the maximum outgoing bytes the transport will buffer before applying write backpressure. | ||
| /// </summary> | ||
| public long? MaxWriteBufferSize { get; set; } = 64 * 1024; | ||
|
|
||
| /// <summary> | ||
| /// Inline application and transport continuations instead of dispatching to the threadpool. | ||
| /// </summary> | ||
| /// <remarks> | ||
| /// This will run application code on the IO thread which is why this is unsafe. | ||
| /// It is recommended to set the DOTNET_SYSTEM_NET_SOCKETS_INLINE_COMPLETIONS environment variable to '1' when using this setting to also inline the completions | ||
| /// at the runtime layer as well. | ||
| /// This setting can make performance worse if there is expensive work that will end up holding onto the IO thread for longer than needed. | ||
| /// Test to make sure this setting helps performance. | ||
| /// </remarks> | ||
| public bool UnsafePreferInlineScheduling { get; set; } | ||
|
|
||
| internal Func<MemoryPool<byte>> MemoryPoolFactory { get; set; } = PinnedBlockMemoryPoolFactory.Create; | ||
| } | ||
| } |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Oops, something went wrong.
Add this suggestion to a batch that can be applied as a single commit.
This suggestion is invalid because no changes were made to the code.
Suggestions cannot be applied while the pull request is closed.
Suggestions cannot be applied while viewing a subset of changes.
Only one suggestion per line can be applied in a batch.
Add this suggestion to a batch that can be applied as a single commit.
Applying suggestions on deleted lines is not supported.
You must change the existing code in this line in order to create a valid suggestion.
Outdated suggestions cannot be applied.
This suggestion has been applied or marked resolved.
Suggestions cannot be applied from pending reviews.
Suggestions cannot be applied on multi-line comments.
Suggestions cannot be applied while the pull request is queued to merge.
Suggestion cannot be applied right now. Please check back later.
Uh oh!
There was an error while loading. Please reload this page.