/*
 * Licensed to the Apache Software Foundation (ASF) under one or more
 * contributor license agreements. See the NOTICE file distributed with
 * this work for additional information regarding copyright ownership.
 * The ASF licenses this file to You under the Apache license, Version 2.0
 * (the "License"); you may not use this file except in compliance with
 * the License. You may obtain a copy of the License at
 *
 *      http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the license for the specific language governing permissions and
 * limitations under the license.
 */
package org.apache.logging.log4j.core;

import org.apache.logging.log4j.Level;
import org.apache.logging.log4j.LogManager;
import org.junit.BeforeClass;
import org.junit.Test;
import org.junit.Assert;

import static org.junit.Assert.assertEquals;
import static org.junit.Assert.assertNotNull;
import static org.junit.Assert.assertFalse;
import static org.junit.Assert.assertTrue;

/**
 *
 */
public class SimplePerfTest {

    private static org.apache.logging.log4j.Logger logger = LogManager.getLogger(SimplePerfTest.class.getName());
    private volatile Level lvl = Level.DEBUG;
    private static final int LOOP_CNT = 100000000;
    private static final int WARMUP = 1000;
    private static long maxTime;

    @BeforeClass
    public static void setupClass() {
        for (int i=0; i < WARMUP; ++i) {
            if (overhead(i, LOOP_CNT)) {
                System.out.println("help!");
            }
        }

        Timer timer = new Timer("Setup", LOOP_CNT);
        timer.start();
        for (int i=0; i < LOOP_CNT; ++i) {
            if (overhead(i, LOOP_CNT)) {
                System.out.println("help!");
            }
        }
        timer.stop();
        maxTime = timer.getElapsedNanoTime();
        System.out.println(timer.toString());
    }

    @Test
    public void debugDisabled() {
        Timer timer = new Timer("DebugDisabled", LOOP_CNT);
        timer.start();
        for (int i=0; i < LOOP_CNT; ++i) {
            logger.isDebugEnabled();
        }
        timer.stop();
        System.out.println(timer.toString());
        assertTrue("Timer exceeded max time of " + maxTime, maxTime > timer.getElapsedNanoTime());
    }

    @Test
    public void debugLogger() {
        Timer timer = new Timer("DebugLogger", LOOP_CNT);
        timer.start();
        for (int i=0; i < LOOP_CNT; ++i) {
            logger.debug("This is a test");
        }
        timer.stop();
        System.out.println(timer.toString());
        assertTrue("Timer exceeded max time of " + maxTime, maxTime > timer.getElapsedNanoTime());
    }
    /*
    @Test
    public void errorLogger() {
        Timer timer = new Timer("ErrorLogger", 10);
        timer.start();
        for (int i=0; i < 10; ++i) {
            logger.error("This is a test");
        }
        timer.stop();
        System.out.println(timer.toString());
    }  */

    /*
     * Try to generate some overhead that can't be optimized well. Not sure how accurate this is,
     * but the point is simply to insure that changes made don't suddenly cause performance issues.
     */
    private static boolean overhead(int i, int j) {
        for (int k=j; k < j+12; ++k) {
            if (i > k) {
                return true;
            }
            if (i == k) {
                return true;
            }
            if (i < 0) {
                return true;
            }
        }
        return false;
    }
}

@@ -996,16 +996,101 @@
 ssert;%0A%0A
+import java.util.Random;%0Aimport java.util.UUID;%0Aimport java.util.logging.LogRecord;%0A%0A
 import s
@@ -1594,63 +1594,396 @@
 me;%0A
-%0A    @BeforeClass%0A    public static void setupClass() %7B
+    private static int DEPTH = 2;%0A    private static NotRandom rand = new NotRandom();%0A    private static int RAND_SIZE = 10000;%0A    private static int%5B%5D values = new int%5BRAND_SIZE%5D;%0A%0A    @BeforeClass%0A    public static void setupClass() %7B%0A%0A        Random r = new Random(WARMUP);%0A%0A        for (int i=0; i %3C RAND_SIZE; ++i) %7B%0A            values%5Bi%5D = r.nextInt(Integer.MAX_VALUE);%0A        %7D%0A
 %0A   
@@ -2041,35 +2041,29 @@
 f (overhead(
-i, LOOP_CNT
+DEPTH
 )) %7B%0A       
@@ -2272,19 +2272,13 @@
 ead(
-i, LOOP_CNT
+DEPTH
 )) %7B
@@ -3804,15 +3804,8 @@
 nt i
-, int j
 ) %7B%0A
@@ -3816,35 +3816,20 @@
     
-for (int k=j; k %3C j+12; ++k
+while (i %3E 0
 ) %7B%0A
@@ -3848,13 +3848,27 @@
 if (
-i %3E k
+rand.nextInt() %3C= 0
 ) %7B%0A
@@ -3926,86 +3926,227 @@
     
-if (i == k) %7B%0A                return true;%0A            %7D%0A            if (i %3C 0
+--i;%0A        %7D%0A        return false;%0A    %7D%0A%0A    private static class NotRandom extends Random%0A    %7B%0A        private int index = 0;%0A%0A        @Override%0A        public int nextInt() %7B%0A            if (index %3E= values.length
 ) %7B%0A
@@ -4157,35 +4157,33 @@
             
-return true
+index = 0
 ;%0A          
@@ -4196,33 +4196,47 @@
     
-  %7D%0A
       
-  
 return 
-false;
+values%5Bindex++%5D;%0A        %7D
 %0A   

Try a different baseline algorithm