MongoFramework
MongoFramework copied to clipboard
Custom Entity Serializer
Continuing from the ideas of #87 , it is probably worthwhile to make a custom entity serializer that uses the EntityDefinition
rather than BsonClassMap
. Every type that gets an entity definition would automatically get this new serializer applied to it and all of its properties.
While I don't have any specific numbers at the moment, I think there is a good chance to squeeze a lot better performance while lowering allocations.
Ultimately this would still need to use the BsonSerializerRegistry
and be otherwise compatible with the default serializer system in the MongoDB driver.
First, this should start with a benchmark of the current serialization system to see what we are dealing with.
One thing I'm interested in is actually seeing if I could leverage System.Text.Json as the bulk of the serialization logic instead. It would make working with the driver's built-in systems difficult and JSON != BSON however there still might be ways it can perform really well in this setup.
While looking into a different issue, I stumbled across the BsonClassMapSerializationProvider
and BsonClassMapSerializer<TClass>
- it is effectively these two classes I'd be replicating but using my entity definition. These classes are fairly isolated however the BsonClassMapSerializationProvider
is registered and acts somewhat greedy in terms of serialization. I can't just add my serialization registration to the end as it will still go through the BsonClassMapSerializationProvider
.
private static void CreateSerializerRegistry()
{
__serializerRegistry = new BsonSerializerRegistry();
__typeMappingSerializationProvider = new TypeMappingSerializationProvider();
// order matters. It's in reverse order of how they'll get consumed
__serializerRegistry.RegisterSerializationProvider(new BsonClassMapSerializationProvider());
__serializerRegistry.RegisterSerializationProvider(new DiscriminatedInterfaceSerializationProvider());
__serializerRegistry.RegisterSerializationProvider(new CollectionsSerializationProvider());
__serializerRegistry.RegisterSerializationProvider(new PrimitiveSerializationProvider());
__serializerRegistry.RegisterSerializationProvider(new AttributedSerializationProvider());
__serializerRegistry.RegisterSerializationProvider(__typeMappingSerializationProvider);
__serializerRegistry.RegisterSerializationProvider(new BsonObjectModelSerializationProvider());
}
I will need to use reflection and "inject" my provider before it. It is backed by a private ConcurrentStack
so it is gonna be messy. I need to keep it there as MongoFramework shouldn't clobber the library - there should be a way to trigger this initialization on assembly load automatically so the user doesn't need to bother configuring it.
@Turnerj, How is work moving along on this one ? Is there something I can help with ?
Haven't been able to work on this more yet myself.
The first, most important part is identifying how much performance the serializer is currently leaving on the table. Need to establish a benchmark for how well the existing one works - allocations and throughput. The benchmark needs to isolate the BsonClassMapSerializer<TClass>
as that is the core part we are effectively replacing. We need to instantiate it and call its serialize/deserialize methods etc.
Then it is a matter of prototyping a custom serializer on the same example model and seeing how much faster it can be made using entity definitions. We'd still be serializing to BsonDocument
etc but it is the process of serializing to/from it that we would be changing.