From d0104d122ee3e40a1a55599abc0dac0ad43943d0 Mon Sep 17 00:00:00 2001 From: Nikolay Borisenko <22616990+nvborisenko@users.noreply.github.com> Date: Sat, 29 Nov 2025 18:10:48 +0300 Subject: [PATCH 1/5] Rent buffer --- dotnet/src/webdriver/BiDi/WebSocketTransport.cs | 10 +++++++--- 1 file changed, 7 insertions(+), 3 deletions(-) diff --git a/dotnet/src/webdriver/BiDi/WebSocketTransport.cs b/dotnet/src/webdriver/BiDi/WebSocketTransport.cs index c64d4a0f79a15..1edd620a4fdc2 100644 --- a/dotnet/src/webdriver/BiDi/WebSocketTransport.cs +++ b/dotnet/src/webdriver/BiDi/WebSocketTransport.cs @@ -19,6 +19,7 @@ using OpenQA.Selenium.Internal.Logging; using System; +using System.Buffers; using System.IO; using System.Net.WebSockets; using System.Text; @@ -32,7 +33,7 @@ class WebSocketTransport(Uri _uri) : ITransport, IDisposable private readonly static ILogger _logger = Internal.Logging.Log.GetLogger(); private readonly ClientWebSocket _webSocket = new(); - private readonly ArraySegment _receiveBuffer = new(new byte[1024 * 8]); + private readonly byte[] _receiveBuffer = ArrayPool.Shared.Rent(1024 * 8); private readonly SemaphoreSlim _socketSendSemaphoreSlim = new(1, 1); private readonly MemoryStream _sharedMemoryStream = new(); @@ -46,13 +47,15 @@ public async Task ReceiveAsync(CancellationToken cancellationToken) { _sharedMemoryStream.SetLength(0); + ArraySegment segment = new(_receiveBuffer); + WebSocketReceiveResult result; do { - result = await _webSocket.ReceiveAsync(_receiveBuffer, cancellationToken).ConfigureAwait(false); + result = await _webSocket.ReceiveAsync(segment, cancellationToken).ConfigureAwait(false); - _sharedMemoryStream.Write(_receiveBuffer.Array!, _receiveBuffer.Offset, result.Count); + _sharedMemoryStream.Write(segment.Array!, segment.Offset, result.Count); } while (!result.EndOfMessage); @@ -90,5 +93,6 @@ public void Dispose() _webSocket.Dispose(); _sharedMemoryStream.Dispose(); _socketSendSemaphoreSlim.Dispose(); + ArrayPool.Shared.Return(_receiveBuffer); } } From c03d4e19ac4b12dd68364b4c3bf74132b180d626 Mon Sep 17 00:00:00 2001 From: Nikolay Borisenko <22616990+nvborisenko@users.noreply.github.com> Date: Sun, 30 Nov 2025 16:12:58 +0300 Subject: [PATCH 2/5] Fix bazel build --- dotnet/src/webdriver/BUILD.bazel | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/dotnet/src/webdriver/BUILD.bazel b/dotnet/src/webdriver/BUILD.bazel index 0762608e83d68..e989aa6b005ca 100644 --- a/dotnet/src/webdriver/BUILD.bazel +++ b/dotnet/src/webdriver/BUILD.bazel @@ -61,6 +61,7 @@ csharp_library( ], deps = [ nuget_package("Microsoft.Bcl.AsyncInterfaces"), + nuget_package("System.Buffers"), nuget_package("System.Threading.Tasks.Extensions"), nuget_package("System.Memory"), nuget_package("System.Runtime.CompilerServices.Unsafe"), @@ -94,6 +95,7 @@ csharp_library( deps = [ nuget_package("NETStandard.Library"), nuget_package("Microsoft.Bcl.AsyncInterfaces"), + nuget_package("System.Buffers"), nuget_package("System.Threading.Tasks.Extensions"), nuget_package("System.Memory"), nuget_package("System.Runtime.CompilerServices.Unsafe"), @@ -150,6 +152,7 @@ csharp_library( ], deps = [ nuget_package("Microsoft.Bcl.AsyncInterfaces"), + nuget_package("System.Buffers"), nuget_package("System.Threading.Tasks.Extensions"), nuget_package("System.Memory"), nuget_package("System.Runtime.CompilerServices.Unsafe"), @@ -181,6 +184,7 @@ csharp_library( deps = [ nuget_package("NETStandard.Library"), nuget_package("Microsoft.Bcl.AsyncInterfaces"), + nuget_package("System.Buffers"), nuget_package("System.Threading.Tasks.Extensions"), nuget_package("System.Memory"), nuget_package("System.Runtime.CompilerServices.Unsafe"), From 45e10205c6a8b628f5ecff259ec44948b8ad0249 Mon Sep 17 00:00:00 2001 From: Nikolay Borisenko <22616990+nvborisenko@users.noreply.github.com> Date: Sun, 30 Nov 2025 16:16:33 +0300 Subject: [PATCH 3/5] Update WebSocketTransport.cs --- dotnet/src/webdriver/BiDi/WebSocketTransport.cs | 8 ++++++++ 1 file changed, 8 insertions(+) diff --git a/dotnet/src/webdriver/BiDi/WebSocketTransport.cs b/dotnet/src/webdriver/BiDi/WebSocketTransport.cs index 1edd620a4fdc2..6e39bc18f4d89 100644 --- a/dotnet/src/webdriver/BiDi/WebSocketTransport.cs +++ b/dotnet/src/webdriver/BiDi/WebSocketTransport.cs @@ -88,11 +88,19 @@ public async Task SendAsync(byte[] data, CancellationToken cancellationToken) } } + private bool _disposed; + public void Dispose() { + if (_disposed) + { + return; + } + _webSocket.Dispose(); _sharedMemoryStream.Dispose(); _socketSendSemaphoreSlim.Dispose(); ArrayPool.Shared.Return(_receiveBuffer); + _disposed = true; } } From 8075c2cd2822da2051a13e757e98e75875ecdf48 Mon Sep 17 00:00:00 2001 From: Nikolay Borisenko <22616990+nvborisenko@users.noreply.github.com> Date: Sun, 30 Nov 2025 16:47:23 +0300 Subject: [PATCH 4/5] ReleaseBuffer --- dotnet/src/webdriver/BiDi/WebSocketTransport.cs | 15 ++++++++++++++- 1 file changed, 14 insertions(+), 1 deletion(-) diff --git a/dotnet/src/webdriver/BiDi/WebSocketTransport.cs b/dotnet/src/webdriver/BiDi/WebSocketTransport.cs index 6e39bc18f4d89..4689f83c491b1 100644 --- a/dotnet/src/webdriver/BiDi/WebSocketTransport.cs +++ b/dotnet/src/webdriver/BiDi/WebSocketTransport.cs @@ -100,7 +100,20 @@ public void Dispose() _webSocket.Dispose(); _sharedMemoryStream.Dispose(); _socketSendSemaphoreSlim.Dispose(); - ArrayPool.Shared.Return(_receiveBuffer); + ReleaseBuffer(); _disposed = true; } + + ~WebSocketTransport() + { + ReleaseBuffer(); + } + + private void ReleaseBuffer() + { + if (_receiveBuffer is not null) + { + ArrayPool.Shared.Return(_receiveBuffer); + } + } } From 5dc6173d03461c6963cea32227198a193f34bd68 Mon Sep 17 00:00:00 2001 From: Nikolay Borisenko <22616990+nvborisenko@users.noreply.github.com> Date: Sun, 30 Nov 2025 16:55:57 +0300 Subject: [PATCH 5/5] Minor warnings --- dotnet/src/webdriver/BiDi/Module.cs | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/dotnet/src/webdriver/BiDi/Module.cs b/dotnet/src/webdriver/BiDi/Module.cs index df3101a195b39..4e90c2db7df67 100644 --- a/dotnet/src/webdriver/BiDi/Module.cs +++ b/dotnet/src/webdriver/BiDi/Module.cs @@ -23,9 +23,9 @@ namespace OpenQA.Selenium.BiDi; public abstract class Module { - protected BiDi BiDi { get; private set; } + protected BiDi BiDi { get; private set; } = null!; - protected Broker Broker { get; private set; } + protected Broker Broker { get; private set; } = null!; protected abstract void Initialize(JsonSerializerOptions options);