j-easy / easy-rules

The simple, stupid rules engine for Java
https://github.com/j-easy/easy-rules/wiki
MIT License
4.88k stars 1.05k forks source link

Optimize performance by using method handle to replace reflect #401

Open BOFA1ex opened 1 year ago

BOFA1ex commented 1 year ago

RuleProxy has been sped up by caching the reflective access in v3.4.0. However it still invokes native reflection, and there is a better way to optimize the performance : e.g. https://github.com/FasterXML/jackson-modules-base/blob/2.15/blackbird/README.md benchmarks https://github.com/FasterXML/jackson-modules-base/blob/2.15/blackbird/benchmarks/README.md

It could use BiConsumer to replace the ActionMethodOrderBean#method prop. And using consumer.accept(target, actualParameters.toArray()) BTW, importing extra dependencies of method handle is needless, it's better than ASM.

static class MethodHandleRule {
    void execute(Object[] args){
        System.out.println("Using method handle as lambda.");
        System.out.println("And print args: " + Arrays.toString(args));
    }
}

@SuppressWarnings({"rawtypes", "unchecked"})
public void usingMethodHandle() throws Throwable {
    final MethodHandleRule target = new MethodHandleRule();
    final MethodHandles.Lookup lookup = MethodHandles.lookup();
    final Method method = target.getClass().getDeclaredMethod("execute", Object[].class);
    final MethodHandle methodHandle = lookup.unreflect(method);

    final Object functionInterface = LambdaMetafactory.metafactory(lookup, "accept",
            methodType(BiConsumer.class), methodType(void.class, Object.class, Object.class),
            methodHandle, methodHandle.type()
    ).getTarget().invoke();

    final BiConsumer consumer = (BiConsumer) functionInterface;
    final Object args = new Object[]{"123", "234"};
    consumer.accept(target, args);
}