PluginManager#collectPlugins() performs quite some package scanning sequentially. I have the impression that this operation can simply be parallelized as follows:
Stream .of(inputs) .flatMap(input -> Stream .of(ops) .map(op -> new Object[]{op, input})) .parallel() .map(opAndInput -> { final Function<Input, Output> op = opAndInput[0]; final Input input = opAndInput[1]; return op.accept(input); }) .reduce(this::merge); Here input denotes the packages and ops denote the independent sequential steps performed in collectPlugins(). I don't know about the overhead of this call, but the above simple effort might be worth a shot. What do you think?