Skip to content

Commit eede7d8

Browse files
author
Jimmy Byrd
committed
Adds ArrayPool for shared buffer usage
1 parent 142baba commit eede7d8

6 files changed

Lines changed: 92 additions & 32 deletions

File tree

src/FSharp.Control.Websockets.TPL/FSharp.Control.Websockets.TPL.fs

Lines changed: 54 additions & 23 deletions
Original file line numberDiff line numberDiff line change
@@ -66,6 +66,11 @@ module WebSocket =
6666
open System.Net.WebSockets
6767
open FSharp.Control.Tasks.V2
6868

69+
#if NETSTANDARD2_1
70+
open System.Buffers
71+
let private arrayPool = ArrayPool<byte>.Shared
72+
#endif
73+
6974
/// **Description**
7075
///
7176
/// Same as the `DefaultReceiveBufferSize` and `DefaultClientSendBufferSize` from the internal [WebSocketHelpers]( https://referencesource.microsoft.com/#System/net/System/Net/WebSockets/WebSocketHelpers.cs,285b8b64a4da6851).
@@ -190,15 +195,27 @@ module WebSocket =
190195
/// **Exceptions**
191196
///
192197
let sendMessage (socket : WebSocket) (bufferSize : int) (messageType : WebSocketMessageType) (cancellationToken : CancellationToken) (readableStream : #IO.Stream) = task {
193-
let buffer = Array.create (bufferSize) Byte.MinValue
198+
let buffer =
199+
#if NETSTANDARD2_1
200+
arrayPool.Rent(bufferSize)
201+
#else
202+
Array.create (bufferSize) Byte.MinValue
203+
#endif
194204
let mutable moreToRead = true
195-
while moreToRead && isWebsocketOpen socket do
196-
let! read = readableStream.ReadAsync(buffer, 0, buffer.Length)
197-
if read > 0 then
198-
do! send socket (ArraySegment(buffer |> Array.take read)) messageType false cancellationToken
199-
else
200-
moreToRead <- false
201-
do! send socket (ArraySegment(Array.empty)) messageType true cancellationToken
205+
try
206+
while moreToRead && isWebsocketOpen socket do
207+
let! read = readableStream.ReadAsync(buffer, 0, buffer.Length)
208+
if read > 0 then
209+
do! send socket (ArraySegment(buffer |> Array.take read)) messageType false cancellationToken
210+
else
211+
moreToRead <- false
212+
do! send socket (ArraySegment(Array.empty)) messageType true cancellationToken
213+
finally
214+
#if NETSTANDARD2_1
215+
arrayPool.Return(buffer,true)
216+
#else
217+
()
218+
#endif
202219
}
203220

204221

@@ -248,24 +265,38 @@ module WebSocket =
248265
/// **Exceptions**
249266
///
250267
let receiveMessage (socket : WebSocket) (bufferSize : int) (messageType : WebSocketMessageType) (cancellationToken : CancellationToken) (writeableStream : IO.Stream) = task {
251-
let buffer = new ArraySegment<Byte>( Array.create (bufferSize) Byte.MinValue)
268+
let innerbuffer =
269+
#if NETSTANDARD2_1
270+
arrayPool.Rent(bufferSize)
271+
#else
272+
Array.create (bufferSize) Byte.MinValue
273+
#endif
274+
let buffer = new ArraySegment<Byte>(innerbuffer)
252275
let mutable moreToRead = true
253276
let mutable mainResult = Unchecked.defaultof<ReceiveStreamResult>
254-
while moreToRead do
255-
let! result = receive socket buffer cancellationToken
256-
match result with
257-
| result when result.MessageType = WebSocketMessageType.Close || socket.State = WebSocketState.CloseReceived || socket.State = WebSocketState.CloseSent ->
258-
do! socket.CloseOutputAsync(WebSocketCloseStatus.NormalClosure, "Close received", cancellationToken)
259-
moreToRead <- false
260-
mainResult <- Closed(socket.CloseStatus.Value, socket.CloseStatusDescription)
261-
| result ->
262-
if result.MessageType <> messageType then
263-
failwithf "Invalid message type received %A, expected %A" result.MessageType messageType
264-
do! writeableStream.WriteAsync(buffer.Array, 0, result.Count)
265-
if result.EndOfMessage then
277+
try
278+
while moreToRead do
279+
let! result = receive socket buffer cancellationToken
280+
match result with
281+
| result when result.MessageType = WebSocketMessageType.Close || socket.State = WebSocketState.CloseReceived || socket.State = WebSocketState.CloseSent ->
282+
do! socket.CloseOutputAsync(WebSocketCloseStatus.NormalClosure, "Close received", cancellationToken)
266283
moreToRead <- false
267-
mainResult <- Stream writeableStream
268-
return mainResult
284+
mainResult <- Closed(socket.CloseStatus.Value, socket.CloseStatusDescription)
285+
| result ->
286+
if result.MessageType <> messageType then
287+
failwithf "Invalid message type received %A, expected %A" result.MessageType messageType
288+
do! writeableStream.WriteAsync(buffer.Array, 0, result.Count)
289+
if result.EndOfMessage then
290+
moreToRead <- false
291+
mainResult <- Stream writeableStream
292+
return mainResult
293+
finally
294+
#if NETSTANDARD2_1
295+
arrayPool.Return(innerbuffer,true)
296+
#else
297+
()
298+
#endif
299+
269300
}
270301

271302
/// One of the possible results from reading a whole message from a websocket.

src/FSharp.Control.Websockets.TPL/FSharp.Control.Websockets.TPL.fsproj

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,7 @@
11
<?xml version="1.0" encoding="utf-8"?>
22
<Project Sdk="Microsoft.NET.Sdk">
33
<PropertyGroup>
4-
<TargetFrameworks>netstandard2.0;net461</TargetFrameworks>
4+
<TargetFrameworks>netstandard2.1;netstandard2.0;net461</TargetFrameworks>
55
<GenerateDocumentationFile>true</GenerateDocumentationFile>
66
</PropertyGroup>
77
<PropertyGroup>

src/FSharp.Control.Websockets/FSharp.Control.Websockets.fs

Lines changed: 34 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -100,6 +100,11 @@ module WebSocket =
100100
open System
101101
open System.Net.WebSockets
102102

103+
#if NETSTANDARD2_1
104+
open System.Buffers
105+
let private arrayPool = ArrayPool<byte>.Shared
106+
#endif
107+
103108
/// **Description**
104109
///
105110
/// Same as the `DefaultReceiveBufferSize` and `DefaultClientSendBufferSize` from the internal [WebSocketHelpers]( https://referencesource.microsoft.com/#System/net/System/Net/WebSockets/WebSocketHelpers.cs,285b8b64a4da6851).
@@ -220,7 +225,12 @@ module WebSocket =
220225
/// **Exceptions**
221226
///
222227
let sendMessage (socket : WebSocket) (bufferSize : int) (messageType : WebSocketMessageType) (readableStream : #IO.Stream) = async {
223-
let buffer = Array.create (bufferSize) Byte.MinValue
228+
let buffer =
229+
#if NETSTANDARD2_1
230+
arrayPool.Rent(bufferSize)
231+
#else
232+
Array.create (bufferSize) Byte.MinValue
233+
#endif
224234

225235
let rec sendMessage' () = async {
226236
if isWebsocketOpen socket then
@@ -231,7 +241,14 @@ module WebSocket =
231241
else
232242
do! (asyncSend socket (ArraySegment(Array.empty)) messageType true)
233243
}
234-
return! sendMessage'()
244+
try
245+
return! sendMessage'()
246+
finally
247+
#if NETSTANDARD2_1
248+
arrayPool.Return(buffer,true)
249+
#else
250+
()
251+
#endif
235252
}
236253

237254

@@ -278,7 +295,13 @@ module WebSocket =
278295
/// **Exceptions**
279296
///
280297
let receiveMessage (socket : WebSocket) (bufferSize : int) (messageType : WebSocketMessageType) (writeableStream : IO.Stream) = async {
281-
let buffer = new ArraySegment<Byte>( Array.create (bufferSize) Byte.MinValue)
298+
let innerbuffer =
299+
#if NETSTANDARD2_1
300+
arrayPool.Rent(bufferSize)
301+
#else
302+
Array.create (bufferSize) Byte.MinValue
303+
#endif
304+
let buffer = new ArraySegment<Byte>(innerbuffer)
282305

283306
let rec readTillEnd' () = async {
284307
let! result = asyncReceive socket buffer
@@ -296,8 +319,14 @@ module WebSocket =
296319
else
297320
return! readTillEnd' ()
298321
}
299-
300-
return! readTillEnd' ()
322+
try
323+
return! readTillEnd' ()
324+
finally
325+
#if NETSTANDARD2_1
326+
arrayPool.Return(innerbuffer,true)
327+
#else
328+
()
329+
#endif
301330

302331
}
303332

src/FSharp.Control.Websockets/FSharp.Control.Websockets.fsproj

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,7 @@
11
<?xml version="1.0" encoding="utf-8"?>
22
<Project Sdk="Microsoft.NET.Sdk">
33
<PropertyGroup>
4-
<TargetFrameworks>netstandard2.0;net461</TargetFrameworks>
4+
<TargetFrameworks>netstandard2.1;netstandard2.0;net461</TargetFrameworks>
55
<GenerateDocumentationFile>true</GenerateDocumentationFile>
66
</PropertyGroup>
77
<PropertyGroup>

tests/FSharp.Control.Websockets.TPL.Tests/FSharp.Control.Websockets.TPL.Tests.fsproj

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -2,7 +2,7 @@
22
<Project Sdk="Microsoft.NET.Sdk">
33
<PropertyGroup>
44
<OutputType>Exe</OutputType>
5-
<TargetFrameworks>netcoreapp2.1</TargetFrameworks>
5+
<TargetFrameworks>netcoreapp2.1;netcoreapp2.2;netcoreapp3.0</TargetFrameworks>
66
<!-- <RuntimeFrameworkVersion>2.1.0</RuntimeFrameworkVersion> -->
77
</PropertyGroup>
88
<ItemGroup>

tests/FSharp.Control.Websockets.Tests/FSharp.Control.Websockets.Tests.fsproj

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -2,7 +2,7 @@
22
<Project Sdk="Microsoft.NET.Sdk">
33
<PropertyGroup>
44
<OutputType>Exe</OutputType>
5-
<TargetFrameworks>netcoreapp2.1</TargetFrameworks>
5+
<TargetFrameworks>netcoreapp2.1;netcoreapp2.2;netcoreapp3.0</TargetFrameworks>
66
<!-- <RuntimeFrameworkVersion>2.1.0</RuntimeFrameworkVersion> -->
77
</PropertyGroup>
88
<ItemGroup>

0 commit comments

Comments
 (0)