001/** 002 * Logback: the reliable, generic, fast and flexible logging framework. 003 * Copyright (C) 1999-2015, QOS.ch. All rights reserved. 004 * 005 * This program and the accompanying materials are dual-licensed under 006 * either the terms of the Eclipse Public License v1.0 as published by 007 * the Eclipse Foundation 008 * 009 * or (per the licensee's choosing) 010 * 011 * under the terms of the GNU Lesser General Public License version 2.1 012 * as published by the Free Software Foundation. 013 */ 014package ch.qos.logback.classic; 015 016import static org.junit.Assert.assertTrue; 017 018import org.junit.Before; 019import org.junit.Ignore; 020import org.junit.Test; 021 022import ch.qos.logback.classic.spi.ILoggingEvent; 023import ch.qos.logback.classic.turbo.NOPTurboFilter; 024import ch.qos.logback.core.UnsynchronizedAppenderBase; 025import ch.qos.logback.core.helpers.NOPAppender; 026import ch.qos.logback.core.testUtil.EnvUtilForTests; 027 028@Ignore 029public class LoggerPerfTest { 030 031 static final long NANOS_IN_ONE_SEC = 1000 * 1000 * 1000L; 032 static long NORMAL_RUN_LENGTH = 1 * 1000 * 1000; 033 static long SHORTENED_RUN_LENGTH = 500 * 1000; 034 035 LoggerContext lc = new LoggerContext(); 036 Logger lbLogger = lc.getLogger(this.getClass()); 037 org.slf4j.Logger logger = lbLogger; 038 039 @Before 040 public void setUp() throws Exception { 041 } 042 043 // =========================================================================== 044 @Test 045 public void durationOfDisabledLogsWith_1_NOPFilter() { 046 double avg = computeDurationOfDisabledLogsWith_1_NOPFilter(1, NORMAL_RUN_LENGTH); 047 System.out.println("durationOfDisabledLogsWith_1_NOPFilter=" + avg); 048 @SuppressWarnings("unused") 049 long referencePerf = 60; 050 051 //BogoPerf.assertDuration(avg, referencePerf, CoreConstants.REFERENCE_BIPS); 052 } 053 054 double computeDurationOfDisabledLogsWith_1_NOPFilter(int numOfFilters, long len) { 055 for (int i = 0; i < numOfFilters; i++) { 056 lc.addTurboFilter(new NOPTurboFilter()); 057 } 058 lbLogger.setLevel(Level.OFF); 059 for (long i = 0; i < len; i++) 060 logger.debug("Toto"); 061 062 long start = System.nanoTime(); 063 for (long i = 0; i < len; i++) 064 logger.debug("Toto"); 065 066 return (System.nanoTime() - start) / len; 067 } 068 069 // =========================================================================== 070 @Test 071 public void durationOfIsDebugEnabled() { 072 double avg = computedurationOfIsDebugEnabled(10 * NORMAL_RUN_LENGTH); 073 System.out.println("durationOfIsDebugEnabled=" + avg); 074 075 @SuppressWarnings("unused") 076 long referencePerf = 15; 077 //BogoPerf.assertDuration(avg, referencePerf, CoreConstants.REFERENCE_BIPS); 078 } 079 080 double computedurationOfIsDebugEnabled(final long len) { 081 lbLogger.setLevel(Level.OFF); 082 for (long i = 0; i < len; i++) 083 logger.isDebugEnabled(); 084 Thread.yield(); 085 for (long i = 0; i < len; i++) 086 logger.isDebugEnabled(); 087 088 long start = System.nanoTime(); 089 for (long i = 0; i < len; i++) 090 logger.isDebugEnabled(); 091 return (System.nanoTime() - start) / len; 092 } 093 094 // =========================================================================== 095 @Test 096 public void durationOfDisabledLog_NoParameters() { 097 double avg = computeDurationOfDisabledLog_NoParameters(10 * NORMAL_RUN_LENGTH); 098 System.out.println("durationOfDisabledLog_NoParameters=" + avg); 099 100 @SuppressWarnings("unused") 101 long referencePerf = 18; 102 //BogoPerf.assertDuration(avg, referencePerf, CoreConstants.REFERENCE_BIPS); 103 } 104 105 double computeDurationOfDisabledLog_NoParameters(final long len) { 106 lbLogger.setLevel(Level.OFF); 107 for (long i = 0; i < len; i++) 108 logger.debug("Toto"); 109 Thread.yield(); 110 for (long i = 0; i < len; i++) 111 logger.debug("Toto"); 112 Thread.yield(); 113 114 long start = System.nanoTime(); 115 for (long i = 0; i < len; i++) 116 logger.debug("Toto"); 117 return (System.nanoTime() - start) / len; 118 } 119 120 // =========================================================================== 121 122 @Test 123 public void durationOfDisabledLog_1_Parameter() { 124 double avgDuration = computeDurationOfDisabledLog_1_Parameter(NORMAL_RUN_LENGTH); 125 System.out.println("durationOfDisabledLog_1_Parameter=" + avgDuration); 126 127 @SuppressWarnings("unused") 128 long referencePerf = 30; 129 //BogoPerf.assertDuration(avgDuration, referencePerf, CoreConstants.REFERENCE_BIPS); 130 } 131 132 double computeDurationOfDisabledLog_1_Parameter(long len) { 133 lbLogger.setLevel(Level.OFF); 134 final Object o = new Object(); 135 for (long i = 0; i < len; i++) 136 logger.debug("Toto {}", o); 137 138 long start = System.nanoTime(); 139 for (long i = 0; i < len; i++) 140 logger.debug("Toto {}", o); 141 142 long end = System.nanoTime(); 143 return (end - start) / len; 144 } 145 146 // =========================================================================== 147 148 @Test 149 public void durationOfEnabledLog() { 150 if (EnvUtilForTests.isLinux()) { 151 // the JIT on Linux behaves very differently 152 return; 153 } 154 double avgDuration = computeDurationOfEnabledLog(SHORTENED_RUN_LENGTH); 155 System.out.println("durationOfEnabledLog=" + avgDuration); 156 157 @SuppressWarnings("unused") 158 long referencePerf = 800; 159 // BogoPerf.assertDuration(avgDuration, referencePerf, CoreConstants.REFERENCE_BIPS); 160 } 161 162 double computeDurationOfEnabledLog(long len) { 163 lbLogger.setLevel(Level.ALL); 164 165 NOPAppender<ILoggingEvent> nopAppender = new NOPAppender<ILoggingEvent>(); 166 nopAppender.start(); 167 ((ch.qos.logback.classic.Logger) logger).addAppender(nopAppender); 168 for (long i = 0; i < len; i++) { 169 logger.debug("Toto"); 170 } 171 long start = System.nanoTime(); 172 for (long i = 0; i < len; i++) { 173 logger.debug("Toto"); 174 } 175 long end = System.nanoTime(); 176 return (end - start) / len; 177 } 178 179 // =========================================================================== 180 181 @Test 182 public void testThreadedLogging() throws InterruptedException { 183 SleepAppender<ILoggingEvent> appender = new SleepAppender<ILoggingEvent>(); 184 185 int MILLIS_PER_CALL = 250; 186 int NANOS_PER_CALL = 250 * 1000 * 1000; 187 188 appender.setDuration(MILLIS_PER_CALL); 189 appender.start(); 190 191 lbLogger.addAppender(appender); 192 lbLogger.setLevel(Level.DEBUG); 193 long start; 194 long end; 195 int threadCount = 10; 196 int iterCount = 5; 197 TestRunner[] threads = new TestRunner[threadCount]; 198 for (int i = 0; i < threads.length; ++i) { 199 threads[i] = new TestRunner(logger, iterCount); 200 } 201 start = System.nanoTime(); 202 for (Thread thread : threads) { 203 thread.start(); 204 } 205 for (TestRunner thread : threads) { 206 thread.join(); 207 } 208 end = System.nanoTime(); 209 double tolerance = threadCount * .125; // Very little thread contention 210 // should occur in this test. 211 double max = ((((double) NANOS_PER_CALL) / NANOS_IN_ONE_SEC) * iterCount) * tolerance; 212 double serialized = (((double) NANOS_PER_CALL) / NANOS_IN_ONE_SEC) * iterCount * threadCount; 213 double actual = ((double) (end - start)) / NANOS_IN_ONE_SEC; 214 System.out.printf("Sleep duration: %,.4f seconds. Max expected: %,.4f seconds, Serialized: %,.4f\n", actual, max, serialized); 215 assertTrue("Exceeded maximum expected time.", actual < max); 216 } 217 218 // ============================================================ 219 private static class TestRunner extends Thread { 220 private org.slf4j.Logger logger; 221 private long len; 222 223 public TestRunner(org.slf4j.Logger logger, long len) { 224 this.logger = logger; 225 this.len = len; 226 } 227 228 public void run() { 229 Thread.yield(); 230 for (long i = 0; i < len; i++) { 231 logger.debug("Toto"); 232 } 233 } 234 } 235 236 // ============================================================ 237 public static class SleepAppender<E> extends UnsynchronizedAppenderBase<E> { 238 private static long duration = 500; 239 240 public void setDuration(long millis) { 241 duration = millis; 242 } 243 244 @Override 245 protected void append(E eventObject) { 246 try { 247 Thread.sleep(duration); 248 } catch (InterruptedException ie) { 249 // Ignore 250 } 251 } 252 } 253 // ============================================================ 254}