001/* 002 * The contents of this file are subject to the terms of the Common Development and 003 * Distribution License (the License). You may not use this file except in compliance with the 004 * License. 005 * 006 * You can obtain a copy of the License at legal/CDDLv1.0.txt. See the License for the 007 * specific language governing permission and limitations under the License. 008 * 009 * When distributing Covered Software, include this CDDL Header Notice in each file and include 010 * the License file at legal/CDDLv1.0.txt. If applicable, add the following below the CDDL 011 * Header, with the fields enclosed by brackets [] replaced by your own identifying 012 * information: "Portions copyright [year] [name of copyright owner]". 013 * 014 * Copyright 2016 ForgeRock AS. 015 */ 016 017package org.forgerock.http.handler; 018 019import java.util.concurrent.TimeUnit; 020 021import org.forgerock.http.Filter; 022import org.forgerock.http.Handler; 023import org.forgerock.http.protocol.Request; 024import org.forgerock.http.protocol.Response; 025import org.forgerock.http.protocol.Status; 026import org.forgerock.services.context.Context; 027import org.forgerock.services.context.RootContext; 028import org.forgerock.util.promise.NeverThrowsException; 029import org.forgerock.util.promise.Promise; 030import org.openjdk.jmh.annotations.Benchmark; 031import org.openjdk.jmh.annotations.BenchmarkMode; 032import org.openjdk.jmh.annotations.Fork; 033import org.openjdk.jmh.annotations.Measurement; 034import org.openjdk.jmh.annotations.Mode; 035import org.openjdk.jmh.annotations.OutputTimeUnit; 036import org.openjdk.jmh.annotations.Scope; 037import org.openjdk.jmh.annotations.State; 038import org.openjdk.jmh.annotations.Threads; 039import org.openjdk.jmh.annotations.Warmup; 040import org.openjdk.jmh.runner.Runner; 041import org.openjdk.jmh.runner.RunnerException; 042import org.openjdk.jmh.runner.options.Options; 043import org.openjdk.jmh.runner.options.OptionsBuilder; 044 045@State(Scope.Thread) 046@BenchmarkMode(Mode.Throughput) 047@OutputTimeUnit(TimeUnit.MILLISECONDS) 048@Warmup(iterations = 5, time = 1, timeUnit = TimeUnit.SECONDS) 049@Measurement(iterations = 1, time = 2, timeUnit = TimeUnit.MINUTES) 050@Fork(1) 051@Threads(50) 052public class HandlersChainOfBenchmark { 053 054 private Promise<Response, NeverThrowsException> OK_RESPONSE = 055 Response.newResponsePromise(new Response(Status.OK)); 056 057 private Handler OK_HANDLER = new Handler() { 058 @Override 059 public Promise<Response, NeverThrowsException> handle(final Context context, final Request request) { 060 return OK_RESPONSE; 061 } 062 }; 063 064 // use a non-final, non-static variable in order to prevent JVM optimization 065 private double x = Math.PI; 066 067 private final Filter PASS_THROUGH = new Filter() { 068 @Override 069 public Promise<Response, NeverThrowsException> filter(final Context context, 070 final Request request, 071 final Handler next) { 072 // Prevent constant folding by the JVM 073 if (x == Double.MAX_VALUE) { return null; } 074 return next.handle(context, request); 075 } 076 }; 077 private Request REQUEST = new Request(); 078 private RootContext CONTEXT = new RootContext(); 079 080 private Handler original = Handlers.chainOf(OK_HANDLER, PASS_THROUGH, PASS_THROUGH, PASS_THROUGH, PASS_THROUGH, PASS_THROUGH); 081 082 @Benchmark 083 public Promise<Response, NeverThrowsException> testOriginalChainOf() { 084 return original.handle(CONTEXT, REQUEST); 085 } 086 087 public static void main(String[] args) throws RunnerException { 088 Options opt = new OptionsBuilder() 089 .include(HandlersChainOfBenchmark.class.getSimpleName()) 090 .build(); 091 092 new Runner(opt).run(); 093 } 094 095}