diff --git a/Microsoft.Azure.Cosmos.Encryption.Custom/src/Microsoft.Azure.Cosmos.Encryption.Custom.csproj b/Microsoft.Azure.Cosmos.Encryption.Custom/src/Microsoft.Azure.Cosmos.Encryption.Custom.csproj
index 3b94db54c2..f5a6c610ac 100644
--- a/Microsoft.Azure.Cosmos.Encryption.Custom/src/Microsoft.Azure.Cosmos.Encryption.Custom.csproj
+++ b/Microsoft.Azure.Cosmos.Encryption.Custom/src/Microsoft.Azure.Cosmos.Encryption.Custom.csproj
@@ -43,6 +43,7 @@
+
diff --git a/Microsoft.Azure.Cosmos.Encryption.Custom/src/RentArrayBufferWriter.cs b/Microsoft.Azure.Cosmos.Encryption.Custom/src/RentArrayBufferWriter.cs
deleted file mode 100644
index 5b37ded4fb..0000000000
--- a/Microsoft.Azure.Cosmos.Encryption.Custom/src/RentArrayBufferWriter.cs
+++ /dev/null
@@ -1,211 +0,0 @@
-// ------------------------------------------------------------
-// Copyright (c) Microsoft Corporation. All rights reserved.
-// ------------------------------------------------------------
-
-namespace Microsoft.Azure.Cosmos.Encryption.Custom;
-
-#if NET8_0_OR_GREATER
-
-using System;
-using System.Buffers;
-using System.Diagnostics;
-using System.IO;
-using System.Threading;
-using System.Threading.Tasks;
-
-///
-/// https://gist.github.com/ahsonkhan/c76a1cc4dc7107537c3fdc0079a68b35
-/// Standard ArrayBufferWriter is not using pooled memory
-///
-internal class RentArrayBufferWriter : IBufferWriter, IDisposable
-{
- private const int MinimumBufferSize = 256;
-
- private byte[] rentedBuffer;
- private int written;
- private long committed;
-
- public RentArrayBufferWriter(int initialCapacity = MinimumBufferSize)
- {
- if (initialCapacity <= 0)
- {
- throw new ArgumentException(null, nameof(initialCapacity));
- }
-
- this.rentedBuffer = ArrayPool.Shared.Rent(initialCapacity);
- this.written = 0;
- this.committed = 0;
- }
-
- public (byte[], int) WrittenBuffer
- {
- get
- {
- this.CheckIfDisposed();
-
- return (this.rentedBuffer, this.written);
- }
- }
-
- public Memory WrittenMemory
- {
- get
- {
- this.CheckIfDisposed();
-
- return this.rentedBuffer.AsMemory(0, this.written);
- }
- }
-
- public Span WrittenSpan
- {
- get
- {
- this.CheckIfDisposed();
-
- return this.rentedBuffer.AsSpan(0, this.written);
- }
- }
-
- public int BytesWritten
- {
- get
- {
- this.CheckIfDisposed();
-
- return this.written;
- }
- }
-
- public long BytesCommitted
- {
- get
- {
- this.CheckIfDisposed();
-
- return this.committed;
- }
- }
-
- public void Clear()
- {
- this.CheckIfDisposed();
-
- this.ClearHelper();
- }
-
- private void ClearHelper()
- {
- this.rentedBuffer.AsSpan(0, this.written).Clear();
- this.written = 0;
- }
-
- public async Task CopyToAsync(Stream stream, CancellationToken cancellationToken = default)
- {
- this.CheckIfDisposed();
-
- ArgumentNullException.ThrowIfNull(stream);
-
- await stream.WriteAsync(new Memory(this.rentedBuffer, 0, this.written), cancellationToken).ConfigureAwait(false);
- this.committed += this.written;
-
- this.ClearHelper();
- }
-
- public void CopyTo(Stream stream)
- {
- this.CheckIfDisposed();
-
- ArgumentNullException.ThrowIfNull(stream);
-
- stream.Write(this.rentedBuffer, 0, this.written);
- this.committed += this.written;
-
- this.ClearHelper();
- }
-
- public void Advance(int count)
- {
- this.CheckIfDisposed();
-
- ArgumentOutOfRangeException.ThrowIfLessThan(count, 0);
-
- if (this.written > this.rentedBuffer.Length - count)
- {
- throw new InvalidOperationException("Cannot advance past the end of the buffer.");
- }
-
- this.written += count;
- }
-
- // Returns the rented buffer back to the pool
- public void Dispose()
- {
- if (this.rentedBuffer == null)
- {
- return;
- }
-
- ArrayPool.Shared.Return(this.rentedBuffer, clearArray: true);
- this.rentedBuffer = null;
- this.written = 0;
- }
-
- private void CheckIfDisposed()
- {
- ObjectDisposedException.ThrowIf(this.rentedBuffer == null, this);
- }
-
- public Memory GetMemory(int sizeHint = 0)
- {
- this.CheckIfDisposed();
-
- ArgumentOutOfRangeException.ThrowIfLessThan(sizeHint, 0);
-
- this.CheckAndResizeBuffer(sizeHint);
- return this.rentedBuffer.AsMemory(this.written);
- }
-
- public Span GetSpan(int sizeHint = 0)
- {
- this.CheckIfDisposed();
-
- ArgumentOutOfRangeException.ThrowIfLessThan(sizeHint, 0);
-
- this.CheckAndResizeBuffer(sizeHint);
- return this.rentedBuffer.AsSpan(this.written);
- }
-
- private void CheckAndResizeBuffer(int sizeHint)
- {
- Debug.Assert(sizeHint >= 0);
-
- if (sizeHint == 0)
- {
- sizeHint = MinimumBufferSize;
- }
-
- int availableSpace = this.rentedBuffer.Length - this.written;
-
- if (sizeHint > availableSpace)
- {
- int growBy = sizeHint > this.rentedBuffer.Length ? sizeHint : this.rentedBuffer.Length;
-
- int newSize = checked(this.rentedBuffer.Length + growBy);
-
- byte[] oldBuffer = this.rentedBuffer;
-
- this.rentedBuffer = ArrayPool.Shared.Rent(newSize);
-
- Debug.Assert(oldBuffer.Length >= this.written);
- Debug.Assert(this.rentedBuffer.Length >= this.written);
-
- oldBuffer.AsSpan(0, this.written).CopyTo(this.rentedBuffer);
- ArrayPool.Shared.Return(oldBuffer, clearArray: true);
- }
-
- Debug.Assert(this.rentedBuffer.Length - this.written > 0);
- Debug.Assert(this.rentedBuffer.Length - this.written >= sizeHint);
- }
-}
-#endif
\ No newline at end of file
diff --git a/Microsoft.Azure.Cosmos.Encryption.Custom/src/Transformation/StreamProcessor.Encryptor.cs b/Microsoft.Azure.Cosmos.Encryption.Custom/src/Transformation/StreamProcessor.Encryptor.cs
index a3980ae56a..3679a71908 100644
--- a/Microsoft.Azure.Cosmos.Encryption.Custom/src/Transformation/StreamProcessor.Encryptor.cs
+++ b/Microsoft.Azure.Cosmos.Encryption.Custom/src/Transformation/StreamProcessor.Encryptor.cs
@@ -6,17 +6,21 @@
namespace Microsoft.Azure.Cosmos.Encryption.Custom.Transformation
{
using System;
+ using System.Buffers;
using System.Collections.Generic;
using System.IO;
using System.Text;
using System.Text.Json;
using System.Threading;
using System.Threading.Tasks;
+ using Microsoft.IO;
internal partial class StreamProcessor
{
private readonly byte[] encryptionPropertiesNameBytes = Encoding.UTF8.GetBytes(Constants.EncryptedInfo);
+ private readonly RecyclableMemoryStreamManager streamManager = new ();
+
internal async Task EncryptStreamAsync(
Stream inputStream,
Stream outputStream,
@@ -51,7 +55,7 @@ internal async Task EncryptStreamAsync(
Utf8JsonWriter encryptionPayloadWriter = null;
string encryptPropertyName = null;
- RentArrayBufferWriter bufferWriter = null;
+ RecyclableMemoryStream bufferWriter = null;
while (!isFinalBlock)
{
@@ -112,8 +116,8 @@ long TransformEncryptBuffer(ReadOnlySpan buffer)
case JsonTokenType.StartObject:
if (encryptPropertyName != null && encryptionPayloadWriter == null)
{
- bufferWriter = new RentArrayBufferWriter();
- encryptionPayloadWriter = new Utf8JsonWriter(bufferWriter);
+ bufferWriter = new RecyclableMemoryStream(this.streamManager);
+ encryptionPayloadWriter = new Utf8JsonWriter((IBufferWriter)bufferWriter);
encryptionPayloadWriter.WriteStartObject();
}
else
@@ -132,16 +136,17 @@ long TransformEncryptBuffer(ReadOnlySpan buffer)
if (reader.CurrentDepth == 1 && encryptionPayloadWriter != null)
{
currentWriter.Flush();
- (byte[] bytes, int length) = bufferWriter.WrittenBuffer;
+ byte[] bytes = bufferWriter.GetBuffer();
+ int length = (int)bufferWriter.Length;
ReadOnlySpan encryptedBytes = TransformEncryptPayload(bytes, length, TypeMarker.Object);
writer.WriteBase64StringValue(encryptedBytes);
encryptPropertyName = null;
#pragma warning disable VSTHRD103 // Call async methods when in an async method - this method cannot be async, Utf8JsonReader is ref struct
encryptionPayloadWriter.Dispose();
+ bufferWriter.Dispose();
#pragma warning restore VSTHRD103 // Call async methods when in an async method
encryptionPayloadWriter = null;
- bufferWriter.Dispose();
bufferWriter = null;
}
@@ -149,8 +154,8 @@ long TransformEncryptBuffer(ReadOnlySpan buffer)
case JsonTokenType.StartArray:
if (encryptPropertyName != null && encryptionPayloadWriter == null)
{
- bufferWriter = new RentArrayBufferWriter();
- encryptionPayloadWriter = new Utf8JsonWriter(bufferWriter);
+ bufferWriter = new RecyclableMemoryStream(this.streamManager);
+ encryptionPayloadWriter = new Utf8JsonWriter((IBufferWriter)bufferWriter);
encryptionPayloadWriter.WriteStartArray();
}
else
@@ -164,16 +169,17 @@ long TransformEncryptBuffer(ReadOnlySpan buffer)
if (reader.CurrentDepth == 1 && encryptionPayloadWriter != null)
{
currentWriter.Flush();
- (byte[] bytes, int length) = bufferWriter.WrittenBuffer;
+ byte[] bytes = bufferWriter.GetBuffer();
+ int length = (int)bufferWriter.Length;
ReadOnlySpan encryptedBytes = TransformEncryptPayload(bytes, length, TypeMarker.Array);
writer.WriteBase64StringValue(encryptedBytes);
encryptPropertyName = null;
#pragma warning disable VSTHRD103 // Call async methods when in an async method - this method cannot be async, Utf8JsonReader is ref struct
encryptionPayloadWriter.Dispose();
+ bufferWriter.Dispose();
#pragma warning restore VSTHRD103 // Call async methods when in an async method
encryptionPayloadWriter = null;
- bufferWriter.Dispose();
bufferWriter = null;
}
diff --git a/Microsoft.Azure.Cosmos.Encryption.Custom/tests/Microsoft.Azure.Cosmos.Encryption.Custom.Performance.Tests/Readme.md b/Microsoft.Azure.Cosmos.Encryption.Custom/tests/Microsoft.Azure.Cosmos.Encryption.Custom.Performance.Tests/Readme.md
index 691dbf0a5d..31a77807b2 100644
--- a/Microsoft.Azure.Cosmos.Encryption.Custom/tests/Microsoft.Azure.Cosmos.Encryption.Custom.Performance.Tests/Readme.md
+++ b/Microsoft.Azure.Cosmos.Encryption.Custom/tests/Microsoft.Azure.Cosmos.Encryption.Custom.Performance.Tests/Readme.md
@@ -9,53 +9,53 @@ Job=MediumRun Toolchain=InProcessEmitToolchain IterationCount=15
LaunchCount=2 WarmupCount=10
```
-| Method | DocumentSizeInKb | CompressionAlgorithm | JsonProcessor | Mean | Error | StdDev | Median | Gen0 | Gen1 | Gen2 | Allocated |
-|------------------------ |----------------- |--------------------- |--------------- |------------:|----------:|----------:|------------:|--------:|--------:|--------:|----------:|
-| **Encrypt** | **1** | **None** | **Newtonsoft** | **22.53 μs** | **0.511 μs** | **0.733 μs** | **22.29 μs** | **0.1526** | **0.0305** | **-** | **41784 B** |
-| EncryptToProvidedStream | 1 | None | Newtonsoft | NA | NA | NA | NA | - | - | - | - |
-| Decrypt | 1 | None | Newtonsoft | 26.31 μs | 0.224 μs | 0.322 μs | 26.23 μs | 0.1526 | 0.0305 | - | 41440 B |
-| DecryptToProvidedStream | 1 | None | Newtonsoft | NA | NA | NA | NA | - | - | - | - |
-| **Encrypt** | **1** | **None** | **Stream** | **12.85 μs** | **0.095 μs** | **0.143 μs** | **12.84 μs** | **0.0610** | **0.0153** | **-** | **17528 B** |
-| EncryptToProvidedStream | 1 | None | Stream | 13.00 μs | 0.096 μs | 0.141 μs | 12.98 μs | 0.0458 | 0.0153 | - | 11392 B |
-| Decrypt | 1 | None | Stream | 13.01 μs | 0.152 μs | 0.228 μs | 13.05 μs | 0.0458 | 0.0153 | - | 12672 B |
-| DecryptToProvidedStream | 1 | None | Stream | 13.48 μs | 0.132 μs | 0.197 μs | 13.45 μs | 0.0458 | 0.0153 | - | 11504 B |
-| **Encrypt** | **1** | **Brotli** | **Newtonsoft** | **27.94 μs** | **0.226 μs** | **0.338 μs** | **27.96 μs** | **0.1526** | **0.0305** | **-** | **38064 B** |
-| EncryptToProvidedStream | 1 | Brotli | Newtonsoft | NA | NA | NA | NA | - | - | - | - |
-| Decrypt | 1 | Brotli | Newtonsoft | 33.49 μs | 0.910 μs | 1.335 μs | 33.99 μs | 0.1221 | - | - | 41064 B |
-| DecryptToProvidedStream | 1 | Brotli | Newtonsoft | NA | NA | NA | NA | - | - | - | - |
-| **Encrypt** | **1** | **Brotli** | **Stream** | **21.15 μs** | **1.037 μs** | **1.521 μs** | **20.52 μs** | **0.0610** | **0.0305** | **-** | **16584 B** |
-| EncryptToProvidedStream | 1 | Brotli | Stream | 20.57 μs | 0.213 μs | 0.292 μs | 20.57 μs | 0.0305 | - | - | 11672 B |
-| Decrypt | 1 | Brotli | Stream | 21.14 μs | 2.212 μs | 3.311 μs | 19.46 μs | 0.0305 | - | - | 13216 B |
-| DecryptToProvidedStream | 1 | Brotli | Stream | 19.60 μs | 0.439 μs | 0.600 μs | 19.52 μs | 0.0305 | - | - | 12048 B |
-| **Encrypt** | **10** | **None** | **Newtonsoft** | **84.82 μs** | **3.002 μs** | **4.208 μs** | **83.32 μs** | **0.6104** | **0.1221** | **-** | **170993 B** |
-| EncryptToProvidedStream | 10 | None | Newtonsoft | NA | NA | NA | NA | - | - | - | - |
-| Decrypt | 10 | None | Newtonsoft | 112.98 μs | 15.294 μs | 21.934 μs | 100.38 μs | 0.6104 | 0.1221 | - | 157425 B |
-| DecryptToProvidedStream | 10 | None | Newtonsoft | NA | NA | NA | NA | - | - | - | - |
-| **Encrypt** | **10** | **None** | **Stream** | **39.63 μs** | **0.658 μs** | **0.923 μs** | **39.41 μs** | **0.3052** | **0.0610** | **-** | **82928 B** |
-| EncryptToProvidedStream | 10 | None | Stream | 36.59 μs | 0.272 μs | 0.399 μs | 36.57 μs | 0.1221 | - | - | 37048 B |
-| Decrypt | 10 | None | Stream | 28.64 μs | 0.378 μs | 0.517 μs | 28.59 μs | 0.1221 | 0.0305 | - | 29520 B |
-| DecryptToProvidedStream | 10 | None | Stream | 27.61 μs | 0.237 μs | 0.332 μs | 27.64 μs | 0.0610 | 0.0305 | - | 18416 B |
-| **Encrypt** | **10** | **Brotli** | **Newtonsoft** | **115.28 μs** | **3.336 μs** | **4.677 μs** | **113.71 μs** | **0.6104** | **0.1221** | **-** | **168065 B** |
-| EncryptToProvidedStream | 10 | Brotli | Newtonsoft | NA | NA | NA | NA | - | - | - | - |
-| Decrypt | 10 | Brotli | Newtonsoft | 118.98 μs | 1.530 μs | 2.195 μs | 118.76 μs | 0.4883 | - | - | 144849 B |
-| DecryptToProvidedStream | 10 | Brotli | Newtonsoft | NA | NA | NA | NA | - | - | - | - |
-| **Encrypt** | **10** | **Brotli** | **Stream** | **90.10 μs** | **3.136 μs** | **4.693 μs** | **88.92 μs** | **0.2441** | **-** | **-** | **63809 B** |
-| EncryptToProvidedStream | 10 | Brotli | Stream | 97.27 μs | 1.885 μs | 2.703 μs | 97.35 μs | 0.1221 | - | - | 32465 B |
-| Decrypt | 10 | Brotli | Stream | 58.48 μs | 0.956 μs | 1.372 μs | 58.59 μs | 0.1221 | 0.0610 | - | 30064 B |
-| DecryptToProvidedStream | 10 | Brotli | Stream | 59.12 μs | 1.160 μs | 1.664 μs | 59.14 μs | 0.0610 | - | - | 18960 B |
-| **Encrypt** | **100** | **None** | **Newtonsoft** | **1,199.74 μs** | **42.805 μs** | **64.069 μs** | **1,206.48 μs** | **23.4375** | **21.4844** | **21.4844** | **1677978 B** |
-| EncryptToProvidedStream | 100 | None | Newtonsoft | NA | NA | NA | NA | - | - | - | - |
-| Decrypt | 100 | None | Newtonsoft | 1,177.48 μs | 25.746 μs | 38.535 μs | 1,172.04 μs | 17.5781 | 15.6250 | 15.6250 | 1260228 B |
-| DecryptToProvidedStream | 100 | None | Newtonsoft | NA | NA | NA | NA | - | - | - | - |
-| **Encrypt** | **100** | **None** | **Stream** | **636.72 μs** | **31.468 μs** | **47.099 μs** | **630.15 μs** | **16.6016** | **16.6016** | **16.6016** | **678066 B** |
-| EncryptToProvidedStream | 100 | None | Stream | 383.33 μs | 7.441 μs | 10.671 μs | 384.69 μs | 4.3945 | 4.3945 | 4.3945 | 230133 B |
-| Decrypt | 100 | None | Stream | 384.93 μs | 12.519 μs | 18.738 μs | 383.59 μs | 5.8594 | 5.8594 | 5.8594 | 230753 B |
-| DecryptToProvidedStream | 100 | None | Stream | 295.19 μs | 7.094 μs | 10.618 μs | 296.11 μs | 3.4180 | 3.4180 | 3.4180 | 119116 B |
-| **Encrypt** | **100** | **Brotli** | **Newtonsoft** | **1,178.06 μs** | **63.246 μs** | **94.664 μs** | **1,152.03 μs** | **13.6719** | **11.7188** | **9.7656** | **1379183 B** |
-| EncryptToProvidedStream | 100 | Brotli | Newtonsoft | NA | NA | NA | NA | - | - | - | - |
-| Decrypt | 100 | Brotli | Newtonsoft | 1,175.01 μs | 41.917 μs | 61.441 μs | 1,156.01 μs | 11.7188 | 9.7656 | 9.7656 | 1124274 B |
-| DecryptToProvidedStream | 100 | Brotli | Newtonsoft | NA | NA | NA | NA | - | - | - | - |
-| **Encrypt** | **100** | **Brotli** | **Stream** | **757.11 μs** | **19.549 μs** | **29.260 μs** | **754.55 μs** | **10.7422** | **10.7422** | **10.7422** | **479493 B** |
-| EncryptToProvidedStream | 100 | Brotli | Stream | 563.46 μs | 9.960 μs | 14.284 μs | 561.60 μs | 2.9297 | 2.9297 | 2.9297 | 180637 B |
-| Decrypt | 100 | Brotli | Stream | 542.34 μs | 14.514 μs | 21.724 μs | 542.04 μs | 6.8359 | 6.8359 | 6.8359 | 231162 B |
-| DecryptToProvidedStream | 100 | Brotli | Stream | 463.69 μs | 9.130 μs | 12.800 μs | 460.71 μs | 3.4180 | 3.4180 | 3.4180 | 119506 B |
+| Method | DocumentSizeInKb | CompressionAlgorithm | JsonProcessor | Mean | Error | StdDev | Median | Gen0 | Gen1 | Gen2 | Allocated |
+|------------------------ |----------------- |--------------------- |-------------- |------------:|----------:|----------:|------------:|--------:|--------:|--------:|----------:|
+| **Encrypt** | **1** | **None** | **Newtonsoft** | **22.51 μs** | **0.393 μs** | **0.576 μs** | **22.63 μs** | **0.1526** | **0.0305** | **-** | **41784 B** |
+| EncryptToProvidedStream | 1 | None | Newtonsoft | NA | NA | NA | NA | - | - | - | - |
+| Decrypt | 1 | None | Newtonsoft | 27.10 μs | 0.124 μs | 0.174 μs | 27.07 μs | 0.1526 | 0.0305 | - | 41440 B |
+| DecryptToProvidedStream | 1 | None | Newtonsoft | NA | NA | NA | NA | - | - | - | - |
+| **Encrypt** | **1** | **None** | **Stream** | **12.82 μs** | **0.063 μs** | **0.091 μs** | **12.78 μs** | **0.0610** | **0.0153** | **-** | **17768 B** |
+| EncryptToProvidedStream | 1 | None | Stream | 12.86 μs | 0.127 μs | 0.190 μs | 12.86 μs | 0.0458 | 0.0153 | - | 11632 B |
+| Decrypt | 1 | None | Stream | 12.90 μs | 0.169 μs | 0.253 μs | 12.89 μs | 0.0458 | 0.0153 | - | 12672 B |
+| DecryptToProvidedStream | 1 | None | Stream | 13.60 μs | 0.189 μs | 0.271 μs | 13.58 μs | 0.0458 | 0.0153 | - | 11504 B |
+| **Encrypt** | **1** | **Brotli** | **Newtonsoft** | **28.87 μs** | **0.346 μs** | **0.474 μs** | **28.74 μs** | **0.1526** | **0.0305** | **-** | **38064 B** |
+| EncryptToProvidedStream | 1 | Brotli | Newtonsoft | NA | NA | NA | NA | - | - | - | - |
+| Decrypt | 1 | Brotli | Newtonsoft | 35.28 μs | 0.905 μs | 1.269 μs | 35.40 μs | 0.1221 | - | - | 41064 B |
+| DecryptToProvidedStream | 1 | Brotli | Newtonsoft | NA | NA | NA | NA | - | - | - | - |
+| **Encrypt** | **1** | **Brotli** | **Stream** | **21.52 μs** | **0.750 μs** | **1.026 μs** | **21.21 μs** | **0.0610** | **0.0305** | **-** | **16824 B** |
+| EncryptToProvidedStream | 1 | Brotli | Stream | 20.80 μs | 0.228 μs | 0.312 μs | 20.76 μs | 0.0305 | - | - | 11912 B |
+| Decrypt | 1 | Brotli | Stream | 19.55 μs | 0.443 μs | 0.636 μs | 19.33 μs | 0.0305 | - | - | 13216 B |
+| DecryptToProvidedStream | 1 | Brotli | Stream | 19.86 μs | 0.192 μs | 0.270 μs | 19.82 μs | 0.0305 | - | - | 12048 B |
+| **Encrypt** | **10** | **None** | **Newtonsoft** | **96.62 μs** | **10.278 μs** | **15.384 μs** | **86.34 μs** | **0.6104** | **0.1221** | **-** | **170993 B** |
+| EncryptToProvidedStream | 10 | None | Newtonsoft | NA | NA | NA | NA | - | - | - | - |
+| Decrypt | 10 | None | Newtonsoft | 106.98 μs | 3.407 μs | 5.100 μs | 104.40 μs | 0.6104 | 0.1221 | - | 157425 B |
+| DecryptToProvidedStream | 10 | None | Newtonsoft | NA | NA | NA | NA | - | - | - | - |
+| **Encrypt** | **10** | **None** | **Stream** | **39.15 μs** | **0.200 μs** | **0.281 μs** | **39.16 μs** | **0.3052** | **0.0610** | **-** | **83168 B** |
+| EncryptToProvidedStream | 10 | None | Stream | 39.27 μs | 2.127 μs | 2.982 μs | 39.00 μs | 0.1221 | - | - | 37288 B |
+| Decrypt | 10 | None | Stream | 28.94 μs | 0.369 μs | 0.518 μs | 28.91 μs | 0.0916 | 0.0305 | - | 29520 B |
+| DecryptToProvidedStream | 10 | None | Stream | 27.56 μs | 0.167 μs | 0.235 μs | 27.54 μs | 0.0610 | 0.0305 | - | 18416 B |
+| **Encrypt** | **10** | **Brotli** | **Newtonsoft** | **116.87 μs** | **0.707 μs** | **0.991 μs** | **116.89 μs** | **0.6104** | **0.1221** | **-** | **168065 B** |
+| EncryptToProvidedStream | 10 | Brotli | Newtonsoft | NA | NA | NA | NA | - | - | - | - |
+| Decrypt | 10 | Brotli | Newtonsoft | 144.59 μs | 14.519 μs | 21.282 μs | 139.95 μs | 0.4883 | - | - | 144849 B |
+| DecryptToProvidedStream | 10 | Brotli | Newtonsoft | NA | NA | NA | NA | - | - | - | - |
+| **Encrypt** | **10** | **Brotli** | **Stream** | **91.28 μs** | **3.359 μs** | **5.027 μs** | **89.89 μs** | **0.2441** | **-** | **-** | **64049 B** |
+| EncryptToProvidedStream | 10 | Brotli | Stream | 98.61 μs | 1.831 μs | 2.741 μs | 99.15 μs | 0.1221 | - | - | 32705 B |
+| Decrypt | 10 | Brotli | Stream | 60.11 μs | 1.366 μs | 2.044 μs | 59.71 μs | 0.1221 | 0.0610 | - | 30064 B |
+| DecryptToProvidedStream | 10 | Brotli | Stream | 58.15 μs | 1.689 μs | 2.422 μs | 58.25 μs | - | - | - | 18960 B |
+| **Encrypt** | **100** | **None** | **Newtonsoft** | **1,087.44 μs** | **15.865 μs** | **23.254 μs** | **1,085.47 μs** | **21.4844** | **19.5313** | **19.5313** | **1677999 B** |
+| EncryptToProvidedStream | 100 | None | Newtonsoft | NA | NA | NA | NA | - | - | - | - |
+| Decrypt | 100 | None | Newtonsoft | 1,124.12 μs | 15.278 μs | 22.395 μs | 1,123.48 μs | 17.5781 | 15.6250 | 15.6250 | 1260236 B |
+| DecryptToProvidedStream | 100 | None | Newtonsoft | NA | NA | NA | NA | - | - | - | - |
+| **Encrypt** | **100** | **None** | **Stream** | **517.26 μs** | **7.106 μs** | **10.636 μs** | **520.35 μs** | **14.6484** | **14.6484** | **14.6484** | **678303 B** |
+| EncryptToProvidedStream | 100 | None | Stream | 339.83 μs | 5.149 μs | 7.706 μs | 337.59 μs | 4.3945 | 4.3945 | 4.3945 | 230367 B |
+| Decrypt | 100 | None | Stream | 346.38 μs | 10.316 μs | 15.440 μs | 343.34 μs | 6.3477 | 6.3477 | 6.3477 | 230757 B |
+| DecryptToProvidedStream | 100 | None | Stream | 280.22 μs | 4.289 μs | 6.420 μs | 278.61 μs | 3.4180 | 3.4180 | 3.4180 | 119111 B |
+| **Encrypt** | **100** | **Brotli** | **Newtonsoft** | **1,113.95 μs** | **15.209 μs** | **22.764 μs** | **1,103.81 μs** | **13.6719** | **9.7656** | **9.7656** | **1379180 B** |
+| EncryptToProvidedStream | 100 | Brotli | Newtonsoft | NA | NA | NA | NA | - | - | - | - |
+| Decrypt | 100 | Brotli | Newtonsoft | 1,138.03 μs | 8.340 μs | 12.224 μs | 1,137.53 μs | 11.7188 | 9.7656 | 9.7656 | 1124260 B |
+| DecryptToProvidedStream | 100 | Brotli | Newtonsoft | NA | NA | NA | NA | - | - | - | - |
+| **Encrypt** | **100** | **Brotli** | **Stream** | **723.60 μs** | **10.132 μs** | **15.165 μs** | **719.90 μs** | **11.7188** | **11.7188** | **11.7188** | **479748 B** |
+| EncryptToProvidedStream | 100 | Brotli | Stream | 551.93 μs | 7.420 μs | 10.641 μs | 550.24 μs | 2.9297 | 2.9297 | 2.9297 | 180882 B |
+| Decrypt | 100 | Brotli | Stream | 540.31 μs | 12.842 μs | 19.222 μs | 542.34 μs | 6.8359 | 6.8359 | 6.8359 | 231164 B |
+| DecryptToProvidedStream | 100 | Brotli | Stream | 452.60 μs | 3.476 μs | 5.203 μs | 452.38 μs | 3.4180 | 3.4180 | 3.4180 | 119509 B |