-
Notifications
You must be signed in to change notification settings - Fork 25
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<string> 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<string> 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 #272
PoC solution cleans all rented memory. This adds some overhead but keeps the solution safer.
Acknowledgements
- 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