aws / aws/aws-dotnet-messaging

Reduce Allocations in Envelope Serialization

Open
#273 1 comment 1 reaction 0 assignees View on GitHub
feature-request p2 queued
Dominant language
C#
Stars
143
Forks
27
Avg merge
1d 18h
Merged PRs (30d)
4

Description

### Describe the feature

The current implementation of `EnvelopeSerializer` utilizes `JsonNode` for message serialization. While functional, this approach introduces unnecessary allocations and increased memory usage, particularly in high-throughput scenarios. There is an opportunity to significantly reduce allocations and improve performance by leveraging `Utf8JsonWriter` over rented buffers, thereby enabling buffer reuse and minimizing memory overhead per message.

### Use Case

Serialization of any enveloped payload passing through the library.

### Proposed Solution

### Serialization Optimization
#### Replace `JsonNode` Usage:
Transition the serialization process from `JsonNode` to `Utf8JsonWriter`, utilizing rented memory buffers. This change will reduce object allocations and improve memory management, especially under heavy load.

#### Interface Compatibility:
To maintain backward compatibility, the `EnvelopeSerializer.SerializeAsync` method should continue to return a string. In the future, further optimizations could be realized by returning a buffer directly, but such a change would introduce a breaking change to the API.

#### Potential for Future Improvements:
Passing a buffer to `EnvelopeSerializer.SerializeAsync` would allow dropping string allocations. With possible long term solution entirely working on rented buffers only across all layers.

### Interface Enhancements
#### Introduce Non-Allocating Serialization:
The current `IMessageSerializer` interface’s `MessageSerializerResult Serialize` method is incompatible with non-allocating serialization scenarios. To address this, a new method is proposed:

`
ValueTask SerializeToBufferAsync(Utf8JsonWriter writer, object? value, ...);
`
where return value is content type.

* Note: Evaluate whether it is feasible to utilize IBufferedWriter (to avoid tight coupling to Utf8JsonWriter) without disrupting the typical Utf8JsonWriter usage patterns.

#### Incremental Interface Introduction:
To ensure a smooth transition, introduce a new interface, `IJsonWriterMessageSerializer`, which derives from `IMessageSerializer` and adds the proposed non-allocating serialization method. This approach allows incremental adoption without breaking existing consumers.

`
public interface IJsonWriterMessageSerializer : IMessageSerializer
{
ValueTask SerializeToBufferAsync(Utf8JsonWriter writer, object? value, ...);
}
`

#### Runtime Detection and Adaptation:
Serialization code should detect at runtime whether a serializer implements `IJsonWriterMessageSerializer`. If so, it should delegate to the new method. This introduces a minimal runtime overhead (an additional type check) but enables immediate performance gains for updated serializers.

### Other Information

PoC with expectable savings stored in https://github.com/aws/aws-dotnet-messaging/pull/272
PoC solution cleans all rented memory. This adds some overhead but keeps the solution safer.

### Acknowledgements

- [x] I may be able to implement this feature request
- [ ] This feature might incur a breaking change

### AWS.Messaging (or related) package versions

AWS.Messaging 1.0.1

### Targeted .NET Platform

.NET 8

### Operating System and version

any

Contributor guide

Open the contributing guide

Research direction

Start with EnvelopeSerializer and the existing IMessageSerializer contract, then review the referenced PoC in pull request 272. Compare the proposed IJsonWriterMessageSerializer and Utf8JsonWriter approach with the backward-compatible SerializeAsync API. Done means reduced allocations with rented buffers, runtime support for updated serializers, and preserved existing consumers.

Written by the indexing model from the issue text.

Assessment

Tech stack
csharp
Domain
backend, performance
Issue type
Feature
Difficulty
5/5
Estimated time
Over a week
Activity status
Stale
Clarity
Mostly clear
Newbie friendliness
25/100

Get new issues in your inbox

A short digest of beginner-friendly GitHub issues.