Working on a project were I migrated some methods from inline @QueryParam
param lists into @BeanParam
I noticed a significant and unexplained impact in latency.
I am unsure what internals are causing this issue because it does not seem to be just the new Bean creation, since an empty Bean is as fast as no Bean. Also @QueryParam
s added into the Bean increase the latency proportionally, the same definitely does not happen at the method level.
The difference between both forms is huge in terms of latency, the @BeanParam
one takes 20% longer despite doing essentially the same.
@Path("test1")
public Response test1(@QueryParam("instring") String one, @QueryParam("instring2") String two)
vs
public class Params {
@QueryParam("instring") String one;
@QueryParam("instring2") String two;
}
@Path("test2")
public Response test2(@BeanParam Params params)
I have created a minimal example here.
My goal is to find a workaround for this since I really find @BeanParam
very nice to organise groups of params and its not clear to me where the latency increase comes from, perhaps there is some kind of hint I can supply to eliminate the perf hit.
As @paul-samsotha mentioned, the additional latency you are encountering seems to be associated with the reflection used to associate query params with the bean fields after the bean is constructed.
Taking your example, commenting out all the Params
bean fields initially and running the tests multiple times, adding a field back into the Params
bean on each run you get the following results:
No Fields: Commenting all fields out of Params class
15:14:53.664 [main] INFO org.example.ProofOfConcept - Warming up
15:15:35.562 [main] INFO org.example.ProofOfConcept - Warmed up
15:15:49.244 [main] INFO org.example.ProofOfConcept - Reqs1: 731.101 10000 in 13.68
15:16:02.968 [main] INFO org.example.ProofOfConcept - Reqs2: 728.7037 10000 in 13.72
15:16:17.016 [main] INFO org.example.ProofOfConcept - Req2/Req1 1.0032899
Single Field: First param only
15:16:57.160 [main] INFO org.example.ProofOfConcept - Warming up
15:17:26.052 [main] INFO org.example.ProofOfConcept - Warmed up
15:17:39.715 [main] INFO org.example.ProofOfConcept - Reqs1: 732.06445 10000 in 13.66
15:17:54.582 [main] INFO org.example.ProofOfConcept - Reqs2: 672.6759 10000 in 14.87
...
3 Fields: First 3 string params
15:20:33.870 [main] INFO org.example.ProofOfConcept - Warming up
15:21:01.859 [main] INFO org.example.ProofOfConcept - Warmed up
15:21:15.825 [main] INFO org.example.ProofOfConcept - Reqs1: 716.17847 10000 in 13.96
15:21:30.926 [main] INFO org.example.ProofOfConcept - Reqs2: 662.2078 10000 in 15.10
...
All params
15:23:55.339 [main] INFO org.example.ProofOfConcept - Warming up
15:24:25.717 [main] INFO org.example.ProofOfConcept - Warmed up
15:24:39.376 [main] INFO org.example.ProofOfConcept - Reqs1: 732.2789 10000 in 13.66
15:24:55.676 [main] INFO org.example.ProofOfConcept - Reqs2: 613.5346 10000 in 16.30
15:24:55.676 [main] INFO org.example.ProofOfConcept - Req2/Req1 1.1935413
The performance gradually gets worse as more Bean fields are added.
As a workaround you could update your Bean class as follows:
@ToString
public static class Params {
String instring;
String inint;
int inint2;
int inint3;
String inint4;
String inint5;
String inint6;
String inint7;
Params(@Context UriInfo allUri){
MultivaluedMap<String, String> params = allUri.getQueryParameters();
instring = params.getFirst("instring");
inint = params.getFirst("inint");
inint2 = toInt(params.getFirst("inint2"));
inint3 = toInt(params.getFirst("inint3"));
inint4 = params.getFirst("inint4");
inint5 = params.getFirst("inint5");
inint6 = params.getFirst("inint6");
inint7 = params.getFirst("inint7");
}
int toInt(String value){
return nonNull(value) ? Integer.parseInt(value) : -1;
}
}
This update should eliminate the reflection mapping stage and result in improved performance:
15:35:16.713 [main] INFO org.example.ProofOfConcept - Warming up
15:35:45.513 [main] INFO org.example.ProofOfConcept - Warmed up
15:35:59.493 [main] INFO org.example.ProofOfConcept - Reqs1: 715.5123 10000 in 13.98
15:36:13.536 [main] INFO org.example.ProofOfConcept - Reqs2: 712.0986 10000 in 14.04
15:36:13.536 [main] INFO org.example.ProofOfConcept - Req2/Req1 1.004794