Skip to content

Conversation

BorisDog
Copy link
Contributor

This PR introduces custom fast serialization path for Memory<T> and ReadOnlyMemory<T>.
Deserializing Memory/ReadOnlyMemory is x4.5 times faster than regular arrays on .net8, and x7 faster on .net6.

The main performance gain is in the deserialization path, while the main serialization improvements are left out from this PR.
Overflow and truncations checks are not implement yet, as the use-cases this scenario is optimized for exclude such need.

Deserialization performance results:

.net8

Method Mean Error StdDev
ArrayDecoding_int 379.96 ms 6.854 ms 6.076 ms
ArrayDecoding_float 385.77 ms 4.181 ms 3.911 ms
ArrayDecoding_double 351.71 ms 6.262 ms 6.700 ms
MemDecoding_int 85.37 ms 1.638 ms 1.950 ms
MemDecoding_float 87.77 ms 1.738 ms 1.626 ms
MemDecoding_double 93.51 ms 1.448 ms 1.283 ms

.net6

Method Mean Error StdDev
ArrayDecoding_int 792.8 ms 11.57 ms 10.83 ms
ArrayDecoding_float 916.5 ms 7.86 ms 6.96 ms
ArrayDecoding_double 838.2 ms 10.08 ms 9.43 ms
MemDecoding_int 107.9 ms 2.13 ms 2.09 ms
MemDecoding_float 120.0 ms 1.97 ms 1.84 ms
MemDecoding_double 123.2 ms 1.96 ms 1.63 ms

@BorisDog BorisDog requested a review from a team as a code owner May 23, 2024 21:30
Copy link
Contributor

@JamesKovacs JamesKovacs left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

LGTM. Just a question about supported value types.

};
break;
default:
throw new NotSupportedException($"Not supported memory type {typeof(TItem)}. Only primitive numeric types are supported.");
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Do we want to support decimal, bool, and char as well? nuint and nint seem reasonable to omit.

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Yes we do, ideally we'd support as much primitive types as possible.
It's quick to add, thanks.

!(__isByte && representation == BsonType.Binary))
{
throw new ArgumentOutOfRangeException(nameof(representation));
}
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

We will want to eventually support serialization to BSON vector (BSON Binary subtype 9) for all value types. But that can be done in the context of a new ticket.

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Yup, it will be easy to add additional representation here.

}
else
{
var inner = e.InnerException.Should().BeOfType<TypeInitializationException>().Subject.InnerException;
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I would prefer to avoid such exceptions. Should we move the failing code from static ctor to some helper method?

@BorisDog BorisDog requested a review from sanych-sun May 27, 2024 19:59
Copy link
Member

@sanych-sun sanych-sun left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

LGTM

@BorisDog BorisDog merged commit 2f5beb8 into mongodb:master Jun 5, 2024
@BorisDog BorisDog deleted the csharp4807 branch June 5, 2024 22:53
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

3 participants