Welcome to mirror list, hosted at ThFree Co, Russian Federation.

github.com/aspnet/MessagePack-CSharp.git - Unnamed repository; edit this file 'description' to name the repository.
summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorAndrew Arnott <andrew.arnott@microsoft.com>2022-06-23 20:01:23 +0300
committerAndrew Arnott <andrew.arnott@microsoft.com>2022-06-23 20:32:55 +0300
commit9a2acd8e1bcc843e4ab9ff704f688749d526ee88 (patch)
tree30b8a2665d920bf7ca4611e9251c411f3524d40f
parent888ecb280ba620a2de1d8445b6661fb3e22ffcf7 (diff)
Add option to avoid large buffer allocations
Allocating 1MB buffers contribute to the large object heap and should be avoidable for applications that it is a problem for.
-rw-r--r--src/MessagePack.UnityClient/Assets/Scripts/MessagePack/MessagePackSerializer.cs5
-rw-r--r--src/MessagePack.UnityClient/Assets/Scripts/MessagePack/MessagePackSerializerOptions.cs33
-rw-r--r--src/MessagePack.UnityClient/Assets/Scripts/Tests/ShareTests/MessagePackSerializerOptionsTests.cs31
-rw-r--r--src/MessagePack/net6.0/PublicAPI.Unshipped.txt2
-rw-r--r--src/MessagePack/netcoreapp3.1/PublicAPI.Unshipped.txt2
-rw-r--r--src/MessagePack/netstandard2.0/PublicAPI.Unshipped.txt4
6 files changed, 72 insertions, 5 deletions
diff --git a/src/MessagePack.UnityClient/Assets/Scripts/MessagePack/MessagePackSerializer.cs b/src/MessagePack.UnityClient/Assets/Scripts/MessagePack/MessagePackSerializer.cs
index 24b5373c..8c4a454c 100644
--- a/src/MessagePack.UnityClient/Assets/Scripts/MessagePack/MessagePackSerializer.cs
+++ b/src/MessagePack.UnityClient/Assets/Scripts/MessagePack/MessagePackSerializer.cs
@@ -18,7 +18,6 @@ namespace MessagePack
[System.Diagnostics.CodeAnalysis.SuppressMessage("ApiDesign", "RS0026:Do not add multiple public overloads with optional parameters", Justification = "Each overload has sufficiently unique required parameters.")]
public static partial class MessagePackSerializer
{
- private const int MaxHintSize = 1024 * 1024;
private static MessagePackSerializerOptions defaultOptions;
/// <summary>
@@ -349,7 +348,7 @@ namespace MessagePack
do
{
cancellationToken.ThrowIfCancellationRequested();
- Span<byte> span = sequence.GetSpan(stream.CanSeek ? (int)Math.Min(MaxHintSize, stream.Length - stream.Position) : 0);
+ Span<byte> span = sequence.GetSpan(stream.CanSeek ? (int)Math.Min(options.SuggestedContiguousMemorySize, stream.Length - stream.Position) : 0);
bytesRead = stream.Read(span);
sequence.Advance(bytesRead);
}
@@ -397,7 +396,7 @@ namespace MessagePack
int bytesRead;
do
{
- Memory<byte> memory = sequence.GetMemory(stream.CanSeek ? (int)Math.Min(MaxHintSize, stream.Length - stream.Position) : 0);
+ Memory<byte> memory = sequence.GetMemory(stream.CanSeek ? (int)Math.Min(options.SuggestedContiguousMemorySize, stream.Length - stream.Position) : 0);
bytesRead = await stream.ReadAsync(memory, cancellationToken).ConfigureAwait(false);
sequence.Advance(bytesRead);
}
diff --git a/src/MessagePack.UnityClient/Assets/Scripts/MessagePack/MessagePackSerializerOptions.cs b/src/MessagePack.UnityClient/Assets/Scripts/MessagePack/MessagePackSerializerOptions.cs
index 771aa25f..a9a9ec51 100644
--- a/src/MessagePack.UnityClient/Assets/Scripts/MessagePack/MessagePackSerializerOptions.cs
+++ b/src/MessagePack.UnityClient/Assets/Scripts/MessagePack/MessagePackSerializerOptions.cs
@@ -58,6 +58,7 @@ namespace MessagePack
this.Resolver = copyFrom.Resolver;
this.Compression = copyFrom.Compression;
this.CompressionMinLength = copyFrom.CompressionMinLength;
+ this.SuggestedContiguousMemorySize = copyFrom.SuggestedContiguousMemorySize;
this.OldSpec = copyFrom.OldSpec;
this.OmitAssemblyVersion = copyFrom.OmitAssemblyVersion;
this.AllowAssemblyVersionMismatch = copyFrom.AllowAssemblyVersionMismatch;
@@ -93,6 +94,16 @@ namespace MessagePack
public int CompressionMinLength { get; private set; } = 64;
/// <summary>
+ /// Gets the size of contiguous memory blocks in bytes that may be allocated for buffering purposes.
+ /// </summary>
+ /// <value>The default value is 1MB.</value>
+ /// <remarks>
+ /// Larger values may perform a bit faster, but may result in adding a runtime perf tax due to using the
+ /// <see href="https://docs.microsoft.com/en-us/dotnet/standard/garbage-collection/large-object-heap">Large Object Heap</see>.
+ /// </remarks>
+ public int SuggestedContiguousMemorySize { get; private set; } = 1024 * 1024;
+
+ /// <summary>
/// Gets a value indicating whether to serialize with <see cref="MessagePackWriter.OldSpec"/> set to some value
/// causing messagepack spec compliance to be explicitly set to the old or new format.
/// </summary>
@@ -228,6 +239,28 @@ namespace MessagePack
}
/// <summary>
+ /// Gets a copy of these options with the <see cref="SuggestedContiguousMemorySize"/> property set to a new value.
+ /// </summary>
+ /// <param name="suggestedContiguousMemorySize">The new value for the <see cref="SuggestedContiguousMemorySize"/> property. Must be at least 256.</param>
+ /// <returns>The new instance; or the original if the value is unchanged.</returns>
+ public MessagePackSerializerOptions WithSuggestedContiguousMemorySize(int suggestedContiguousMemorySize)
+ {
+ if (this.SuggestedContiguousMemorySize == suggestedContiguousMemorySize)
+ {
+ return this;
+ }
+
+ if (suggestedContiguousMemorySize < 256)
+ {
+ throw new ArgumentOutOfRangeException(nameof(suggestedContiguousMemorySize), "This should be at least 256");
+ }
+
+ var result = this.Clone();
+ result.SuggestedContiguousMemorySize = suggestedContiguousMemorySize;
+ return result;
+ }
+
+ /// <summary>
/// Gets a copy of these options with the <see cref="OldSpec"/> property set to a new value.
/// </summary>
/// <param name="oldSpec">The new value for the <see cref="OldSpec"/>.</param>
diff --git a/src/MessagePack.UnityClient/Assets/Scripts/Tests/ShareTests/MessagePackSerializerOptionsTests.cs b/src/MessagePack.UnityClient/Assets/Scripts/Tests/ShareTests/MessagePackSerializerOptionsTests.cs
index dfe988f8..0db5157c 100644
--- a/src/MessagePack.UnityClient/Assets/Scripts/Tests/ShareTests/MessagePackSerializerOptionsTests.cs
+++ b/src/MessagePack.UnityClient/Assets/Scripts/Tests/ShareTests/MessagePackSerializerOptionsTests.cs
@@ -14,7 +14,8 @@ public class MessagePackSerializerOptionsTests
.WithOmitAssemblyVersion(true)
.WithResolver(BuiltinResolver.Instance)
.WithOldSpec(false)
- .WithSecurity(MySecurityOptions.Instance);
+ .WithSecurity(MySecurityOptions.Instance)
+ .WithSuggestedContiguousMemorySize(64 * 1024);
[Fact]
public void AllowAssemblyVersionMismatch()
@@ -48,6 +49,16 @@ public class MessagePackSerializerOptionsTests
}
[Fact]
+ public void SuggestedContiguousMemorySize()
+ {
+ Assert.Equal(1024 * 1024, MessagePackSerializerOptions.Standard.SuggestedContiguousMemorySize);
+ Assert.Throws<ArgumentOutOfRangeException>(() => MessagePackSerializerOptions.Standard.WithSuggestedContiguousMemorySize(0));
+ Assert.Throws<ArgumentOutOfRangeException>(() => MessagePackSerializerOptions.Standard.WithSuggestedContiguousMemorySize(4));
+ MessagePackSerializerOptions options = MessagePackSerializerOptions.Standard.WithSuggestedContiguousMemorySize(512);
+ Assert.Equal(512, options.SuggestedContiguousMemorySize);
+ }
+
+ [Fact]
public void OldSpec()
{
Assert.Null(MessagePackSerializerOptions.Standard.OldSpec);
@@ -74,6 +85,7 @@ public class MessagePackSerializerOptionsTests
var mutated = NonDefaultOptions.WithOldSpec(true);
Assert.True(mutated.OldSpec.Value);
Assert.Equal(NonDefaultOptions.Compression, mutated.Compression);
+ Assert.Equal(NonDefaultOptions.SuggestedContiguousMemorySize, mutated.SuggestedContiguousMemorySize);
Assert.Equal(NonDefaultOptions.AllowAssemblyVersionMismatch, mutated.AllowAssemblyVersionMismatch);
Assert.Equal(NonDefaultOptions.OmitAssemblyVersion, mutated.OmitAssemblyVersion);
Assert.Same(NonDefaultOptions.Resolver, mutated.Resolver);
@@ -93,11 +105,25 @@ public class MessagePackSerializerOptionsTests
}
[Fact]
+ public void WithSuggestedContiguousMemorySize_PreservesOtherProperties()
+ {
+ var mutated = NonDefaultOptions.WithSuggestedContiguousMemorySize(612);
+ Assert.Equal(612, mutated.SuggestedContiguousMemorySize);
+ Assert.Equal(NonDefaultOptions.Compression, mutated.Compression);
+ Assert.Equal(NonDefaultOptions.OldSpec, mutated.OldSpec);
+ Assert.Equal(NonDefaultOptions.AllowAssemblyVersionMismatch, mutated.AllowAssemblyVersionMismatch);
+ Assert.Equal(NonDefaultOptions.OmitAssemblyVersion, mutated.OmitAssemblyVersion);
+ Assert.Same(NonDefaultOptions.Resolver, mutated.Resolver);
+ Assert.Same(MySecurityOptions.Instance, mutated.Security);
+ }
+
+ [Fact]
public void WithAllowAssemblyVersionMismatch_PreservesOtherProperties()
{
var mutated = NonDefaultOptions.WithAllowAssemblyVersionMismatch(false);
Assert.False(mutated.AllowAssemblyVersionMismatch);
Assert.Equal(NonDefaultOptions.Compression, mutated.Compression);
+ Assert.Equal(NonDefaultOptions.SuggestedContiguousMemorySize, mutated.SuggestedContiguousMemorySize);
Assert.Equal(NonDefaultOptions.OldSpec, mutated.OldSpec);
Assert.Equal(NonDefaultOptions.OmitAssemblyVersion, mutated.OmitAssemblyVersion);
Assert.Same(NonDefaultOptions.Resolver, mutated.Resolver);
@@ -110,6 +136,7 @@ public class MessagePackSerializerOptionsTests
var mutated = NonDefaultOptions.WithOmitAssemblyVersion(false);
Assert.False(mutated.OmitAssemblyVersion);
Assert.Equal(NonDefaultOptions.Compression, mutated.Compression);
+ Assert.Equal(NonDefaultOptions.SuggestedContiguousMemorySize, mutated.SuggestedContiguousMemorySize);
Assert.Equal(NonDefaultOptions.OldSpec, mutated.OldSpec);
Assert.Equal(NonDefaultOptions.AllowAssemblyVersionMismatch, mutated.AllowAssemblyVersionMismatch);
Assert.Same(NonDefaultOptions.Resolver, mutated.Resolver);
@@ -122,6 +149,7 @@ public class MessagePackSerializerOptionsTests
var mutated = NonDefaultOptions.WithResolver(ContractlessStandardResolver.Instance);
Assert.Same(ContractlessStandardResolver.Instance, mutated.Resolver);
Assert.Equal(NonDefaultOptions.Compression, mutated.Compression);
+ Assert.Equal(NonDefaultOptions.SuggestedContiguousMemorySize, mutated.SuggestedContiguousMemorySize);
Assert.Equal(NonDefaultOptions.OldSpec, mutated.OldSpec);
Assert.Equal(NonDefaultOptions.AllowAssemblyVersionMismatch, mutated.AllowAssemblyVersionMismatch);
Assert.Equal(NonDefaultOptions.OmitAssemblyVersion, mutated.OmitAssemblyVersion);
@@ -135,6 +163,7 @@ public class MessagePackSerializerOptionsTests
Assert.Same(MessagePackSecurity.TrustedData, mutated.Security);
Assert.Same(NonDefaultOptions.Resolver, mutated.Resolver);
Assert.Equal(NonDefaultOptions.Compression, mutated.Compression);
+ Assert.Equal(NonDefaultOptions.SuggestedContiguousMemorySize, mutated.SuggestedContiguousMemorySize);
Assert.Equal(NonDefaultOptions.OldSpec, mutated.OldSpec);
Assert.Equal(NonDefaultOptions.AllowAssemblyVersionMismatch, mutated.AllowAssemblyVersionMismatch);
Assert.Equal(NonDefaultOptions.OmitAssemblyVersion, mutated.OmitAssemblyVersion);
diff --git a/src/MessagePack/net6.0/PublicAPI.Unshipped.txt b/src/MessagePack/net6.0/PublicAPI.Unshipped.txt
index 78006a92..89697310 100644
--- a/src/MessagePack/net6.0/PublicAPI.Unshipped.txt
+++ b/src/MessagePack/net6.0/PublicAPI.Unshipped.txt
@@ -9,6 +9,8 @@ MessagePack.Formatters.TimeOnlyFormatter
MessagePack.Formatters.TimeOnlyFormatter.Deserialize(ref MessagePack.MessagePackReader reader, MessagePack.MessagePackSerializerOptions options) -> System.TimeOnly
MessagePack.Formatters.TimeOnlyFormatter.Serialize(ref MessagePack.MessagePackWriter writer, System.TimeOnly value, MessagePack.MessagePackSerializerOptions options) -> void
MessagePack.MessagePackSerializerOptions.CompressionMinLength.get -> int
+MessagePack.MessagePackSerializerOptions.SuggestedContiguousMemorySize.get -> int
MessagePack.MessagePackSerializerOptions.WithCompressionMinLength(int compressionMinLength) -> MessagePack.MessagePackSerializerOptions
+MessagePack.MessagePackSerializerOptions.WithSuggestedContiguousMemorySize(int suggestedContiguousMemorySize) -> MessagePack.MessagePackSerializerOptions
static readonly MessagePack.Formatters.DateOnlyFormatter.Instance -> MessagePack.Formatters.DateOnlyFormatter
static readonly MessagePack.Formatters.TimeOnlyFormatter.Instance -> MessagePack.Formatters.TimeOnlyFormatter
diff --git a/src/MessagePack/netcoreapp3.1/PublicAPI.Unshipped.txt b/src/MessagePack/netcoreapp3.1/PublicAPI.Unshipped.txt
index 9ba64088..ba449cac 100644
--- a/src/MessagePack/netcoreapp3.1/PublicAPI.Unshipped.txt
+++ b/src/MessagePack/netcoreapp3.1/PublicAPI.Unshipped.txt
@@ -3,4 +3,6 @@ MessagePack.Formatters.StringInterningFormatter.Deserialize(ref MessagePack.Mess
MessagePack.Formatters.StringInterningFormatter.Serialize(ref MessagePack.MessagePackWriter writer, string value, MessagePack.MessagePackSerializerOptions options) -> void
MessagePack.Formatters.StringInterningFormatter.StringInterningFormatter() -> void
MessagePack.MessagePackSerializerOptions.CompressionMinLength.get -> int
+MessagePack.MessagePackSerializerOptions.SuggestedContiguousMemorySize.get -> int
MessagePack.MessagePackSerializerOptions.WithCompressionMinLength(int compressionMinLength) -> MessagePack.MessagePackSerializerOptions
+MessagePack.MessagePackSerializerOptions.WithSuggestedContiguousMemorySize(int suggestedContiguousMemorySize) -> MessagePack.MessagePackSerializerOptions
diff --git a/src/MessagePack/netstandard2.0/PublicAPI.Unshipped.txt b/src/MessagePack/netstandard2.0/PublicAPI.Unshipped.txt
index 49e84ad1..2cdd3d32 100644
--- a/src/MessagePack/netstandard2.0/PublicAPI.Unshipped.txt
+++ b/src/MessagePack/netstandard2.0/PublicAPI.Unshipped.txt
@@ -3,4 +3,6 @@ MessagePack.Formatters.StringInterningFormatter.Deserialize(ref MessagePack.Mess
MessagePack.Formatters.StringInterningFormatter.Serialize(ref MessagePack.MessagePackWriter writer, string value, MessagePack.MessagePackSerializerOptions options) -> void
MessagePack.Formatters.StringInterningFormatter.StringInterningFormatter() -> void
MessagePack.MessagePackSerializerOptions.CompressionMinLength.get -> int
-MessagePack.MessagePackSerializerOptions.WithCompressionMinLength(int compressionMinLength) -> MessagePack.MessagePackSerializerOptions \ No newline at end of file
+MessagePack.MessagePackSerializerOptions.SuggestedContiguousMemorySize.get -> int
+MessagePack.MessagePackSerializerOptions.WithCompressionMinLength(int compressionMinLength) -> MessagePack.MessagePackSerializerOptions
+MessagePack.MessagePackSerializerOptions.WithSuggestedContiguousMemorySize(int suggestedContiguousMemorySize) -> MessagePack.MessagePackSerializerOptions \ No newline at end of file