View Javadoc
1   /*
2    * The contents of this file are subject to the terms of the Common Development and
3    * Distribution License (the License). You may not use this file except in compliance with the
4    * License.
5    *
6    * You can obtain a copy of the License at legal/CDDLv1.0.txt. See the License for the
7    * specific language governing permission and limitations under the License.
8    *
9    * When distributing Covered Software, include this CDDL Header Notice in each file and include
10   * the License file at legal/CDDLv1.0.txt. If applicable, add the following below the CDDL
11   * Header, with the fields enclosed by brackets [] replaced by your own identifying
12   * information: "Portions copyright [year] [name of copyright owner]".
13   *
14   * Copyright 2016 ForgeRock AS.
15   */
16  
17  package org.forgerock.http.handler;
18  
19  import java.util.concurrent.TimeUnit;
20  
21  import org.forgerock.http.Filter;
22  import org.forgerock.http.Handler;
23  import org.forgerock.http.protocol.Request;
24  import org.forgerock.http.protocol.Response;
25  import org.forgerock.http.protocol.Status;
26  import org.forgerock.services.context.Context;
27  import org.forgerock.services.context.RootContext;
28  import org.forgerock.util.promise.NeverThrowsException;
29  import org.forgerock.util.promise.Promise;
30  import org.openjdk.jmh.annotations.Benchmark;
31  import org.openjdk.jmh.annotations.BenchmarkMode;
32  import org.openjdk.jmh.annotations.Fork;
33  import org.openjdk.jmh.annotations.Measurement;
34  import org.openjdk.jmh.annotations.Mode;
35  import org.openjdk.jmh.annotations.OutputTimeUnit;
36  import org.openjdk.jmh.annotations.Scope;
37  import org.openjdk.jmh.annotations.State;
38  import org.openjdk.jmh.annotations.Threads;
39  import org.openjdk.jmh.annotations.Warmup;
40  import org.openjdk.jmh.runner.Runner;
41  import org.openjdk.jmh.runner.RunnerException;
42  import org.openjdk.jmh.runner.options.Options;
43  import org.openjdk.jmh.runner.options.OptionsBuilder;
44  
45  @State(Scope.Thread)
46  @BenchmarkMode(Mode.Throughput)
47  @OutputTimeUnit(TimeUnit.MILLISECONDS)
48  @Warmup(iterations = 5, time = 1, timeUnit = TimeUnit.SECONDS)
49  @Measurement(iterations = 1, time = 2, timeUnit = TimeUnit.MINUTES)
50  @Fork(1)
51  @Threads(50)
52  public class HandlersChainOfBenchmark {
53  
54      private Promise<Response, NeverThrowsException> OK_RESPONSE =
55              Response.newResponsePromise(new Response(Status.OK));
56  
57      private Handler OK_HANDLER = new Handler() {
58          @Override
59          public Promise<Response, NeverThrowsException> handle(final Context context, final Request request) {
60              return OK_RESPONSE;
61          }
62      };
63  
64      // use a non-final, non-static variable in order to prevent JVM optimization
65      private double x = Math.PI;
66  
67      private final Filter PASS_THROUGH = new Filter() {
68          @Override
69          public Promise<Response, NeverThrowsException> filter(final Context context,
70                  final Request request,
71                  final Handler next) {
72              // Prevent constant folding by the JVM
73              if (x == Double.MAX_VALUE) { return null; }
74              return next.handle(context, request);
75          }
76      };
77      private Request REQUEST = new Request();
78      private RootContext CONTEXT = new RootContext();
79  
80      private Handler original = Handlers.chainOf(OK_HANDLER, PASS_THROUGH, PASS_THROUGH, PASS_THROUGH, PASS_THROUGH, PASS_THROUGH);
81  
82      @Benchmark
83      public Promise<Response, NeverThrowsException> testOriginalChainOf() {
84          return original.handle(CONTEXT, REQUEST);
85      }
86  
87      public static void main(String[] args) throws RunnerException {
88          Options opt = new OptionsBuilder()
89                  .include(HandlersChainOfBenchmark.class.getSimpleName())
90                  .build();
91  
92          new Runner(opt).run();
93      }
94  
95  }