Dear Axon developers,
I have found a possible performance issue in the method
GenericUpcasterChain.upcast
Link to the method
which I would like to share with you and get feedback.
In the current implementation for each event read by EventStorageEngine, canUpcast method of all upcasters is called (internally called from the overridden method upcast of Upcaster class), even if a very small portion of registered upcasters is related to the payload type of the event.
For example, let’s assume:
- I have an event which registered with a payload type eventpackage.EventXCreated
- I have registered n upcasters for up-casting deferent version of the event with payload type eventpackage.EventXCreated
- Besides of above-mentioned upcasters I have registered m upcasters for other events, which of-course won’t be used for events with eventpackage.EventXCreated payload type
Then the amount of canUpcast method calls for a single incoming event can be measured with the following formula
O(n + m)
Before I’ll jump the suggestion of possible fix for this issue, let me tell why I consider this us performance issue
- Axon doesn’t have control of over amount of upcasters registered in the chain. this number can be very big depending on the complexity of task and amount of changes needed in the event schemas during the time
- Axon doesn’t have control over performance of canUpcast method. in case of needing to do complex checking inside this overridden method, each canUpcast method can come with a big cost
- Amount of canUpcast calls for the specific event payload type should not have a linear dependency from the amount of all registered upcasters.
I can suggest the following possible solution (maybe it will need some tweaks)
Step #1
Create the intermediate abstract class which will be constructed with payload type (Class<?>), and will have a getter method for that member used in the next step
This abstract class should be extended by all concrete generic upcaster classes provided by axon
Step #2
change the construct of Upcaster chain to get upcasters which extend from abstract class from step #1 and create a mapping from payloadType(retrieved by the new method introduced in step #1) to list of upcasters for that type.
Step #3
change the upcast method of Upcaster chain to first get supported upcastors for the event representation. Then call upcast methods of already filtered upcasters.
This way part of the filtering of upcasters will be owned by axon (payload type match part), as a result, to do the first filtering we’ll spend something like O(log(n+m)), but the amount of upcast calles will be reduced to O(n) we’ll spend.
Thanks in advance for reading through,
Best regards,
Hayk