diff --git a/Neo4j.Driver/Neo4j.Driver/Config.cs b/Neo4j.Driver/Neo4j.Driver/Config.cs
index f45b8ea69..66be415e1 100644
--- a/Neo4j.Driver/Neo4j.Driver/Config.cs
+++ b/Neo4j.Driver/Neo4j.Driver/Config.cs
@@ -232,11 +232,11 @@ public int MaxIdleConnectionPoolSize
/// By default the driver allows the collection of this telemetry.
///
public bool TelemetryDisabled { get; set; }
-
+
///
/// The configuration for the driver's underlying message reading from the network.
///
- public MessageReaderConfig MessageReaderConfig { get; internal set; } = MessageReaderConfig.Default;
+ public MessageReaderConfig MessageReaderConfig { get; internal set; } = new();
}
///
@@ -244,53 +244,50 @@ public int MaxIdleConnectionPoolSize
///
public sealed class MessageReaderConfig
{
- internal static MessageReaderConfig Default { get; } = new();
-
///
/// Constructs a new instance of .
/// The configuration for the driver's underlying message reading from the network.
///
- /// As of 5.15, the driver has migrated the underlying message reading
- /// mechanism utilizing ; this optimizes the reading and memory usage of the driver, and
- /// setting this to true will revert the driver to the legacy message reader.
/// The memory pool for creating buffers when reading messages. The PipeReader will borrow
/// memory from the pool of at least ReadBufferSize size. The message reader can request larger memory blocks to
- /// host an entire message. User code can provide an implementation for monitoring; by default, the driver will use
- /// .NET's pool.
+ /// host an entire message. User code can provide an implementation for monitoring; by default, the driver will
+ /// allocate a new array pool that does not take advantage of shared memory pools.
/// The minimum buffer size to use when renting memory from the pool. The default value
/// is 65,539.
///
///
///
+ ///
+ /// To optimize the memory usage of the driver pass .NET's shared memory pool() as
+ /// the , this should only be used when there is complete trust over the usage of
+ /// shared memory buffers in the application as other components may be using the same memory pool.
+ ///
/// If is less than 1.
- public MessageReaderConfig(bool disablePipelinedMessageReader = false, MemoryPool memoryPool = null, int minBufferSize = -1)
+ public MessageReaderConfig(MemoryPool memoryPool = null, int minBufferSize = -1)
{
- DisablePipelinedMessageReader = disablePipelinedMessageReader;
- if (disablePipelinedMessageReader)
- {
- return;
- }
- MemoryPool = memoryPool ?? MemoryPool.Shared;
if (minBufferSize is < -1 or 0)
{
throw new ArgumentOutOfRangeException(nameof(minBufferSize));
}
+
+ DisablePipelinedMessageReader = false;
MinBufferSize = minBufferSize == -1 ? 65_535 + 4 : minBufferSize;
+ MemoryPool = memoryPool ?? new PipeReaderMemoryPool(MinBufferSize);
StreamPipeReaderOptions = new(MemoryPool, MinBufferSize, leaveOpen: true);
}
-
+
///
/// As of 5.15, the driver has migrated the underlying message reading mechanism utilizing ;
/// this optimizes the reading and memory usage of the driver, and setting this to true will revert the driver to
/// the legacy message reader.
///
- public bool DisablePipelinedMessageReader { get; }
+ internal bool DisablePipelinedMessageReader { get; }
///
/// The memory pool for creating buffers when reading messages. The PipeReader will borrow memory from the pool of
/// at least size. The message reader can request larger memory blocks to host
- /// an entire message. User code can provide an implementation for monitoring; by default, the driver will use
- /// .NET's pool.
+ /// an entire message. User code can provide an implementation for monitoring; by default, the driver will allocate
+ /// a new array pool that does not take advantage of shared memory pools.
///
public MemoryPool MemoryPool { get; }
diff --git a/Neo4j.Driver/Neo4j.Driver/Internal/Util/PipeReaderMemoryPool.cs b/Neo4j.Driver/Neo4j.Driver/Internal/Util/PipeReaderMemoryPool.cs
new file mode 100644
index 000000000..6f9ff5ed4
--- /dev/null
+++ b/Neo4j.Driver/Neo4j.Driver/Internal/Util/PipeReaderMemoryPool.cs
@@ -0,0 +1,94 @@
+// Copyright (c) "Neo4j"
+// Neo4j Sweden AB [https://neo4j.com]
+//
+// Licensed under the Apache License, Version 2.0 (the "License").
+// You may not use this file except in compliance with the License.
+// You may obtain a copy of the License at
+//
+// http://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing, software
+// distributed under the License is distributed on an "AS IS" BASIS,
+// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+// See the License for the specific language governing permissions and
+// limitations under the License.
+
+using System;
+using System.Buffers;
+
+namespace Neo4j.Driver.Internal;
+
+///
+/// Simple memory pool based on the .NET's Pool.
+///
+internal sealed class PipeReaderMemoryPool : MemoryPool
+{
+ private readonly int _defaultSize;
+ private readonly ArrayPool _pool;
+
+ public PipeReaderMemoryPool(int defaultSize)
+ {
+ _defaultSize = defaultSize;
+ _pool = ArrayPool.Create();
+ }
+
+ public override int MaxBufferSize => int.MaxValue;
+
+ public override IMemoryOwner Rent(int minimumBufferSize = -1)
+ {
+ if (minimumBufferSize == -1)
+ {
+ minimumBufferSize = _defaultSize;
+ }
+
+ if (minimumBufferSize < 0 || minimumBufferSize > MaxBufferSize)
+ {
+ throw new ArgumentOutOfRangeException(nameof(minimumBufferSize), minimumBufferSize, "requested size is invalid");
+ }
+
+ return new PooledMemory(minimumBufferSize, _pool);
+ }
+
+ protected override void Dispose(bool disposing)
+ {
+ }
+
+ private sealed class PooledMemory : IMemoryOwner
+ {
+ private byte[] _array;
+ private readonly ArrayPool _pool;
+
+ public PooledMemory(int size, ArrayPool pool)
+ {
+ _array = pool.Rent(size);
+ _pool = pool;
+ }
+
+ public Memory Memory
+ {
+ get
+ {
+ var array = _array;
+ if (array == null)
+ {
+ throw new ObjectDisposedException(nameof(PooledMemory));
+ }
+
+ return new Memory(array);
+ }
+ }
+
+ public void Dispose()
+ {
+ var array = _array;
+
+ if (array == null)
+ {
+ return;
+ }
+
+ _array = null;
+ _pool.Return(array);
+ }
+ }
+}