Methods on rx.Observable that have an argument that take a rx.function.Function can't be extended with groovy extensions.
The RxGroovy extension adds new groovy.lang.Closure version of each method on rx.Observable that has rx.function.Function as an argument. When the closure version is invoked it wraps the closure in a function and invokes the java.lang.reflect.Method directly bypassing any attempt to extend the original.
This PR changes the invoke to use groovy's internal method resolution and caching. This allows additional groovy extensions to be applied. If no extension are present it will use custom generated bytecode to avoid doing reflection.
################## BEFORE
# Run complete. Total time: 00:03:17
Benchmark (size) (source) Mode Samples Score Score error Units
r.l.g.ExtensionPerf.extension 1 in.map({ it + 1}) thrpt 5 3212878.269 29678.977 ops/s
r.l.g.ExtensionPerf.extension 1 in.filter({ it != 0 }) thrpt 5 3497772.417 534053.736 ops/s
r.l.g.ExtensionPerf.extension 1000 in.map({ it + 1}) thrpt 5 18137.493 432.222 ops/s
r.l.g.ExtensionPerf.extension 1000 in.filter({ it != 0 }) thrpt 5 19746.618 886.572 ops/s
r.l.g.ExtensionPerf.extension 1000000 in.map({ it + 1}) thrpt 5 18.842 0.346 ops/s
r.l.g.ExtensionPerf.extension 1000000 in.filter({ it != 0 }) thrpt 5 19.297 0.673 ops/s
################## AFTER
# Run complete. Total time: 00:03:17
Benchmark (size) (source) Mode Samples Score Score error Units
r.l.g.ExtensionPerf.extension 1 in.map({ it + 1}) thrpt 5 4036047.884 117545.855 ops/s
r.l.g.ExtensionPerf.extension 1 in.filter({ it != 0 }) thrpt 5 4161935.126 131375.955 ops/s
r.l.g.ExtensionPerf.extension 1000 in.map({ it + 1}) thrpt 5 19015.365 1228.843 ops/s
r.l.g.ExtensionPerf.extension 1000 in.filter({ it != 0 }) thrpt 5 19754.786 263.644 ops/s
r.l.g.ExtensionPerf.extension 1000000 in.map({ it + 1}) thrpt 5 17.685 6.204 ops/s
r.l.g.ExtensionPerf.extension 1000000 in.filter({ it != 0 }) thrpt 5 18.208 3.433 ops/s
Methods on
rx.Observable
that have an argument that take arx.function.Function
can't be extended with groovy extensions.The RxGroovy extension adds new
groovy.lang.Closure
version of each method onrx.Observable
that hasrx.function.Function
as an argument. When the closure version is invoked it wraps the closure in a function and invokes thejava.lang.reflect.Method
directly bypassing any attempt to extend the original.This PR changes the invoke to use groovy's internal method resolution and caching. This allows additional groovy extensions to be applied. If no extension are present it will use custom generated bytecode to avoid doing reflection.