Optimizing interceptors with function composition
grmble opened this issue · comments
Effectless interceptors and handlers could be composed, reducing the number of steps for the executor and helping with thread pool overhead for async code.
I made a proof of concept here: https://github.com/grmble/interceptor-optimizer
For detailed explanations see the linked README, but the gist is
- interceptors and handlers can opt into optimization by declaring themselves
:composable
via metadata - no async results, no changing the flow of control (queue manipulations or catching exceptions) - the optimizer finds all runs of consecutive composables and composes them
A benchmark for a simple sync example (1 :error
, 1 :enter
, 1 :leave
, 1 handler) gives a 14% improvement. That being said, I care more about composing :leave
blocks that come after async code, but that is harder to measure.
It is not througly tested - I only ever ran the one same example, and I only ever used the sieppari executor, but I do think that the approach shows promise.
The benchmark numbers are from https://github.com/grmble/interceptor-optimizer/blob/master/src/grmble/interceptor_optimizer/dev.clj#L39-L58
Edit: updated line numbers
Related: metosin/sieppari#51