1
2
3
4
5
6
7
8
9
10 package ch.qos.logback.classic;
11
12 import static org.junit.Assert.assertTrue;
13
14 import org.junit.Before;
15 import org.junit.Test;
16 import org.slf4j.helpers.BogoPerf;
17
18 import ch.qos.logback.classic.spi.LoggingEvent;
19 import ch.qos.logback.classic.turbo.NOPTurboFilter;
20 import ch.qos.logback.core.CoreConstants;
21 import ch.qos.logback.core.UnsynchronizedAppenderBase;
22 import ch.qos.logback.core.appender.NOPAppender;
23 import ch.qos.logback.core.testUtil.Env;
24
25 public class LoggerPerfTest {
26
27 static final long NANOS_IN_ONE_SEC = 1000 * 1000 * 1000L;
28 static long NORMAL_RUN_LENGTH = 1 * 1000 * 1000;
29 static long SHORTENED_RUN_LENGTH = 500 * 1000;
30
31 LoggerContext lc = new LoggerContext();
32 Logger lbLogger = lc.getLogger(this.getClass());
33 org.slf4j.Logger logger = lbLogger;
34
35 @Before
36 public void setUp() throws Exception {
37 }
38
39
40 @Test
41 public void durationOfDisabledLogsWith_1_NOPFilter() {
42 double avg = computeDurationOfDisabledLogsWith_1_NOPFilter(1,
43 NORMAL_RUN_LENGTH);
44 System.out.println("durationOfDisabledLogsWith_1_NOPFilter=" + avg);
45 long referencePerf = 60;
46
47 BogoPerf.assertDuration(avg, referencePerf, CoreConstants.REFERENCE_BIPS);
48 }
49
50 double computeDurationOfDisabledLogsWith_1_NOPFilter(int numOfFilters,
51 long len) {
52 for (int i = 0; i < numOfFilters; i++) {
53 lc.addTurboFilter(new NOPTurboFilter());
54 }
55 lbLogger.setLevel(Level.OFF);
56 for (long i = 0; i < len; i++)
57 logger.debug("Toto");
58
59 long start = System.nanoTime();
60 for (long i = 0; i < len; i++)
61 logger.debug("Toto");
62
63 return (System.nanoTime() - start) / len;
64 }
65
66
67 @Test
68 public void durationOfIsDebugEnabled() {
69 double avg = computedurationOfIsDebugEnabled(10 * NORMAL_RUN_LENGTH);
70 System.out.println("durationOfIsDebugEnabled=" + avg);
71
72 long referencePerf = 15;
73 BogoPerf.assertDuration(avg, referencePerf, CoreConstants.REFERENCE_BIPS);
74 }
75
76 double computedurationOfIsDebugEnabled(final long len) {
77 lbLogger.setLevel(Level.OFF);
78 for (long i = 0; i < len; i++)
79 logger.isDebugEnabled();
80
81 long start = System.nanoTime();
82 for (long i = 0; i < len; i++)
83 logger.isDebugEnabled();
84 return (System.nanoTime() - start) / len;
85 }
86
87
88 @Test
89 public void durationOfDisabledLog_NoParameters() {
90 double avg = computeDurationOfDisabledLog_NoParameters(10 * NORMAL_RUN_LENGTH);
91 System.out.println("durationOfDisabledLog_NoParameters=" + avg);
92
93 long referencePerf = 18;
94 BogoPerf.assertDuration(avg, referencePerf, CoreConstants.REFERENCE_BIPS);
95 }
96
97 double computeDurationOfDisabledLog_NoParameters(final long len) {
98 lbLogger.setLevel(Level.OFF);
99 for (long i = 0; i < len; i++)
100 logger.debug("Toto");
101
102 long start = System.nanoTime();
103 for (long i = 0; i < len; i++)
104 logger.debug("Toto");
105 return (System.nanoTime() - start) / len;
106 }
107
108
109
110 @Test
111 public void durationOfDisabledLog_1_Parameter() {
112 double avgDuration = computeDurationOfDisabledLog_1_Parameter(NORMAL_RUN_LENGTH);
113 System.out.println("durationOfDisabledLog_1_Parameter=" + avgDuration);
114
115 long referencePerf = 30;
116 BogoPerf.assertDuration(avgDuration, referencePerf,
117 CoreConstants.REFERENCE_BIPS);
118 }
119
120 double computeDurationOfDisabledLog_1_Parameter(long len) {
121 lbLogger.setLevel(Level.OFF);
122 final Object o = new Object();
123 for (long i = 0; i < len; i++)
124 logger.debug("Toto {}", o);
125
126 long start = System.nanoTime();
127 for (long i = 0; i < len; i++)
128 logger.debug("Toto {}", o);
129
130 long end = System.nanoTime();
131 return (end - start) / len;
132 }
133
134
135
136 @Test
137 public void durationOfEnabledLog() {
138 if (Env.isLinux()) {
139
140 return;
141 }
142 double avgDuration = computeDurationOfEnabledLog(SHORTENED_RUN_LENGTH);
143 System.out.println("durationOfEnabledLog=" + avgDuration);
144
145 long referencePerf = 800;
146 BogoPerf.assertDuration(avgDuration, referencePerf,
147 CoreConstants.REFERENCE_BIPS);
148 }
149
150 double computeDurationOfEnabledLog(long len) {
151 lbLogger.setLevel(Level.ALL);
152
153 NOPAppender<LoggingEvent> nopAppender = new NOPAppender<LoggingEvent>();
154 nopAppender.start();
155 ((ch.qos.logback.classic.Logger) logger).addAppender(nopAppender);
156 for (long i = 0; i < len; i++) {
157 logger.debug("Toto");
158 }
159 long start = System.nanoTime();
160 for (long i = 0; i < len; i++) {
161 logger.debug("Toto");
162 }
163 long end = System.nanoTime();
164 return (end - start) / len;
165 }
166
167
168
169 @Test
170 public void testThreadedLogging() throws InterruptedException {
171 SleepAppender<LoggingEvent> appender = new SleepAppender<LoggingEvent>();
172
173 int MILLIS_PER_CALL = 250;
174 int NANOS_PER_CALL = 250 * 1000 * 1000;
175
176 appender.setDuration(MILLIS_PER_CALL);
177 appender.start();
178
179 lbLogger.addAppender(appender);
180 lbLogger.setLevel(Level.DEBUG);
181 long start;
182 long end;
183 int threadCount = 10;
184 int iterCount = 5;
185 TestRunner[] threads = new TestRunner[threadCount];
186 for (int i = 0; i < threads.length; ++i) {
187 threads[i] = new TestRunner(logger, iterCount);
188 }
189 start = System.nanoTime();
190 for (Thread thread : threads) {
191 thread.start();
192 }
193 for (TestRunner thread : threads) {
194 thread.join();
195 }
196 end = System.nanoTime();
197 double tolerance = threadCount * .125;
198
199 double max = ((((double) NANOS_PER_CALL) / NANOS_IN_ONE_SEC) * iterCount)
200 * tolerance;
201 double serialized = (((double) NANOS_PER_CALL) / NANOS_IN_ONE_SEC)
202 * iterCount * threadCount;
203 double actual = ((double) (end - start)) / NANOS_IN_ONE_SEC;
204 System.out
205 .printf(
206 "Sleep duration: %,.4f seconds. Max expected: %,.4f seconds, Serialized: %,.4f\n",
207 actual, max, serialized);
208 assertTrue("Exceeded maximum expected time.", actual < max);
209 }
210
211
212 private static class TestRunner extends Thread {
213 private org.slf4j.Logger logger;
214 private long len;
215
216 public TestRunner(org.slf4j.Logger logger, long len) {
217 this.logger = logger;
218 this.len = len;
219 }
220
221 public void run() {
222 Thread.yield();
223 for (long i = 0; i < len; i++) {
224 logger.debug("Toto");
225 }
226 }
227 }
228
229
230 public static class SleepAppender<E> extends UnsynchronizedAppenderBase<E> {
231 private static long duration = 500;
232
233 public void setDuration(long millis) {
234 duration = millis;
235 }
236
237 @Override
238 protected void append(E eventObject) {
239 try {
240 Thread.sleep(duration);
241 } catch (InterruptedException ie) {
242
243 }
244 }
245 }
246
247 }