Jersey2 @BeanParam being significantly slower than the alternative

Arkaitz Jimenez :

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 @QueryParams 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.

noconnor :

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

Guess you like

Origin http://10.200.1.11:23101/article/api/json?id=415238&siteId=1