001    /*
002     * Licensed to the Apache Software Foundation (ASF) under one or more
003     * contributor license agreements. See the NOTICE file distributed with
004     * this work for additional information regarding copyright ownership.
005     * The ASF licenses this file to You under the Apache license, Version 2.0
006     * (the "License"); you may not use this file except in compliance with
007     * the License. You may obtain a copy of the License at
008     *
009     *      http://www.apache.org/licenses/LICENSE-2.0
010     *
011     * Unless required by applicable law or agreed to in writing, software
012     * distributed under the License is distributed on an "AS IS" BASIS,
013     * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
014     * See the license for the specific language governing permissions and
015     * limitations under the license.
016     */
017    package org.apache.logging.log4j.perf.jmh;
018    
019    import org.apache.logging.log4j.core.impl.ReflectiveCallerClassUtility;
020    import org.apache.logging.log4j.message.Message;
021    import org.apache.logging.log4j.message.StringFormattedMessage;
022    import org.openjdk.jmh.annotations.GenerateMicroBenchmark;
023    import org.openjdk.jmh.annotations.Level;
024    import org.openjdk.jmh.annotations.Scope;
025    import org.openjdk.jmh.annotations.Setup;
026    import org.openjdk.jmh.annotations.State;
027    import org.openjdk.jmh.logic.BlackHole;
028    import sun.reflect.Reflection;
029    
030    import java.lang.reflect.Constructor;
031    import java.lang.reflect.InvocationTargetException;
032    import java.util.Random;
033    
034    /**
035     * <p>Benchmarks the different ways the caller class can be obtained.
036     * To run this in sampling mode (latency test):</p>
037     * <pre>
038     *     java -jar microbenchmarks.jar ".*ReflectionBenchmark.*" -i 5 -f 1 -wi 5 -bm sample -tu ns
039     * </pre>
040     * <p>To run this in throughput testing mode:</p>
041     * <pre>
042     *     java -jar microbenchmarks.jar ".*ReflectionBenchmark.*" -i 5 -f 1 -wi 5 -bm Throughput -tu ms
043     * </pre>
044     */
045    public class ReflectionBenchmark {
046    
047        @State(Scope.Thread)
048        public static class RandomInteger {
049    
050            private final Random r = new Random();
051    
052            int random;
053    
054            @Setup(Level.Iteration)
055            public void setup() {
056                random = r.nextInt();
057            }
058        }
059    
060        @GenerateMicroBenchmark
061        public void testBaseline(final BlackHole bh) {
062        }
063    
064        @GenerateMicroBenchmark
065        public String getCallerClassNameFromStackTrace(final BlackHole bh) {
066            return new Throwable().getStackTrace()[3].getClassName();
067        }
068    
069        @GenerateMicroBenchmark
070        public String getCallerClassNameReflectively(final BlackHole bh) {
071            return ReflectiveCallerClassUtility.getCaller(3).getName();
072        }
073    
074        @GenerateMicroBenchmark
075        public String getCallerClassNameSunReflection(final BlackHole bh) {
076            return Reflection.getCallerClass(3).getName();
077        }
078    
079        @GenerateMicroBenchmark
080        public Class<?> getStackTraceClassForClassName() throws ClassNotFoundException {
081            return Class.forName(new Throwable().getStackTrace()[3].getClassName());
082        }
083    
084        @GenerateMicroBenchmark
085        public Class<?> getReflectiveCallerClassUtility(final BlackHole bh) {
086            return ReflectiveCallerClassUtility.getCaller(3);
087        }
088    
089        @GenerateMicroBenchmark
090        public Class<?> getDirectSunReflection(final BlackHole bh) {
091            return Reflection.getCallerClass(3);
092        }
093    
094        @GenerateMicroBenchmark
095        public Message getMessageUsingNew(final RandomInteger rng) {
096            return new StringFormattedMessage("Hello %i", rng.random);
097        }
098    
099        @GenerateMicroBenchmark
100        public Message getMessageUsingReflection(final RandomInteger rng)
101            throws NoSuchMethodException, IllegalAccessException, InvocationTargetException, InstantiationException {
102            final Constructor<? extends Message> constructor = StringFormattedMessage.class.getConstructor(String.class,
103                Object[].class);
104            return constructor.newInstance("Hello %i", new Object[]{rng.random});
105        }
106    }