You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@logging.apache.org by rp...@apache.org on 2015/09/13 08:45:46 UTC
logging-log4j2 git commit: LOG4J2-1120 added benchmark
Repository: logging-log4j2
Updated Branches:
refs/heads/master 0999176c4 -> ec611cb6a
LOG4J2-1120 added benchmark
Project: http://git-wip-us.apache.org/repos/asf/logging-log4j2/repo
Commit: http://git-wip-us.apache.org/repos/asf/logging-log4j2/commit/ec611cb6
Tree: http://git-wip-us.apache.org/repos/asf/logging-log4j2/tree/ec611cb6
Diff: http://git-wip-us.apache.org/repos/asf/logging-log4j2/diff/ec611cb6
Branch: refs/heads/master
Commit: ec611cb6abc21c315a08b2b78967f8784d1fd2b4
Parents: 0999176
Author: rpopma <rp...@apache.org>
Authored: Sun Sep 13 15:45:43 2015 +0900
Committer: rpopma <rp...@apache.org>
Committed: Sun Sep 13 15:45:43 2015 +0900
----------------------------------------------------------------------
.../log4j/perf/jmh/LoggerConfigBenchmark.java | 273 +++++++++++++++++++
1 file changed, 273 insertions(+)
----------------------------------------------------------------------
http://git-wip-us.apache.org/repos/asf/logging-log4j2/blob/ec611cb6/log4j-perf/src/main/java/org/apache/logging/log4j/perf/jmh/LoggerConfigBenchmark.java
----------------------------------------------------------------------
diff --git a/log4j-perf/src/main/java/org/apache/logging/log4j/perf/jmh/LoggerConfigBenchmark.java b/log4j-perf/src/main/java/org/apache/logging/log4j/perf/jmh/LoggerConfigBenchmark.java
new file mode 100644
index 0000000..47c540e
--- /dev/null
+++ b/log4j-perf/src/main/java/org/apache/logging/log4j/perf/jmh/LoggerConfigBenchmark.java
@@ -0,0 +1,273 @@
+/*
+ * 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.perf.jmh;
+
+import java.util.concurrent.ArrayBlockingQueue;
+import java.util.concurrent.ConcurrentHashMap;
+import java.util.concurrent.CopyOnWriteArraySet;
+import java.util.concurrent.atomic.AtomicBoolean;
+import java.util.concurrent.atomic.AtomicInteger;
+import java.util.concurrent.locks.Condition;
+import java.util.concurrent.locks.Lock;
+import java.util.concurrent.locks.ReentrantLock;
+
+import org.apache.logging.log4j.Level;
+import org.apache.logging.log4j.core.Filter;
+import org.apache.logging.log4j.core.LogEvent;
+import org.apache.logging.log4j.core.appender.AbstractAppender;
+import org.apache.logging.log4j.core.config.AppenderControl;
+import org.apache.logging.log4j.core.config.LoggerConfig;
+import org.apache.logging.log4j.core.impl.Log4jLogEvent;
+import org.apache.logging.log4j.message.SimpleMessage;
+import org.openjdk.jmh.annotations.Benchmark;
+import org.openjdk.jmh.annotations.Scope;
+import org.openjdk.jmh.annotations.Setup;
+import org.openjdk.jmh.annotations.State;
+import org.openjdk.jmh.annotations.TearDown;
+import org.openjdk.jmh.infra.Blackhole;
+
+// ============================== HOW TO RUN THIS TEST: ====================================
+//
+// In sampling mode (latency test):
+// java -jar log4j-perf/target/benchmarks.jar ".*LoggerConfigBenchmark.*" -i 10 -f 1 -wi 5 -bm sample -tu ns
+//
+// Multi-threading test:
+// java -jar benchmarks.jar ".*LoggerConfigBenchmark.*" -i 10 -f 1 -wi 5 -bm sample -tu ns -t 4
+//
+// Usage help:
+// java -jar log4j-perf/target/benchmarks.jar -help
+//
+@State(Scope.Benchmark)
+public class LoggerConfigBenchmark {
+ private ConcurrentHashMap<String, Long> map1 = new ConcurrentHashMap<String, Long>();
+ private CopyOnWriteArraySet<Long> arraySet1 = new CopyOnWriteArraySet<Long>();
+ private ConcurrentHashMap<String, Long> map3 = new ConcurrentHashMap<String, Long>();
+ private CopyOnWriteArraySet<Long> arraySet3 = new CopyOnWriteArraySet<Long>();
+
+ private ConcurrentHashMap<String, AppenderControl> appenderMap = new ConcurrentHashMap<String, AppenderControl>();
+ private CopyOnWriteArraySet<AppenderControl> appenderSet = new CopyOnWriteArraySet<AppenderControl>();
+ private volatile Filter filter = null;
+ private boolean additive = true;
+ private boolean includeLocation = true;
+ private LoggerConfig parent;
+ private final AtomicInteger counter = new AtomicInteger();
+ private final AtomicBoolean shutdown = new AtomicBoolean(false);
+ private final Lock shutdownLock = new ReentrantLock();
+ private final Condition noLogEvents = shutdownLock.newCondition(); // should only be used when shutdown == true
+ private final LogEvent LOGEVENT = createLogEventWithoutException();
+ private final static String APPENDERNAME = "LIST";
+ private SimpleListAppender listAppender = new SimpleListAppender(APPENDERNAME);
+
+ private static class SimpleListAppender extends AbstractAppender {
+ private static final long serialVersionUID = 1L;
+ private final AtomicInteger count = new AtomicInteger();
+
+ protected SimpleListAppender(String name) {
+ super(name, null, null);
+ }
+
+ @Override
+ public void append(LogEvent event) {
+ count.incrementAndGet();
+ }
+
+ public int size() {
+ return count.get();
+ }
+ }
+
+ @Setup
+ public void setup() {
+ for (int i = 0; i < 3; i++) {
+ map3.put(String.valueOf(i), Long.valueOf(i));
+ arraySet3.add(Long.valueOf(i));
+ }
+ map1.put(String.valueOf(1), Long.valueOf(1));
+ arraySet1.add(Long.valueOf(1));
+
+ listAppender.start();
+ final AppenderControl control = new AppenderControl(listAppender, Level.ALL, null);
+ appenderMap.put(APPENDERNAME, control);
+ appenderSet.add(control);
+ }
+
+ @Benchmark
+ public void testBaseline(final Blackhole bh) {
+ }
+
+ private static LogEvent createLogEventWithoutException() {
+ return new Log4jLogEvent("a.b.c", null, "a.b.c", Level.INFO, new SimpleMessage("abc"), null, null);
+ }
+
+ @Benchmark
+ public long iterMap1Element() {
+ long total = 0;
+ for (Long value : map1.values()) {
+ total += value;
+ }
+ return total;
+ }
+
+ @Benchmark
+ public long iterArraySet1Element() {
+ long total = 0;
+ for (Long value : arraySet1) {
+ total += value;
+ }
+ return total;
+ }
+
+ @Benchmark
+ public long iterMap3Elements() {
+ long total = 0;
+ for (Long value : map3.values()) {
+ total += value;
+ }
+ return total;
+ }
+
+ @Benchmark
+ public long iterArraySet3Element() {
+ long total = 0;
+ for (Long value : arraySet3) {
+ total += value;
+ }
+ return total;
+ }
+
+ @Benchmark
+ public int logWithCountersAndLock() {
+ log(LOGEVENT);
+ return listAppender.size();
+ }
+
+ @Benchmark
+ public int logWithCountersNoLocks() {
+ log2(LOGEVENT);
+ return listAppender.size();
+ }
+
+ @Benchmark
+ public int logWithoutCountersOrLocks() {
+ log3(LOGEVENT);
+ return listAppender.size();
+ }
+
+ /**
+ * Logs an event.
+ *
+ * @param event The log event.
+ */
+ public void log(final LogEvent event) {
+ beforeLogEvent();
+ try {
+ if (!isFiltered(event)) {
+ processLogEvent(event);
+ }
+ } finally {
+ afterLogEvent();
+ }
+ }
+
+ /**
+ * Logs an event.
+ *
+ * @param event The log event.
+ */
+ public void log2(final LogEvent event) {
+ beforeLogEvent();
+ try {
+ if (!isFiltered(event)) {
+ processLogEvent(event);
+ }
+ } finally {
+ afterLogEvent2();
+ }
+ }
+
+ /**
+ * Logs an event.
+ *
+ * @param event The log event.
+ */
+ public void log3(final LogEvent event) {
+ if (!isFiltered(event)) {
+ processLogEvent(event);
+ }
+ }
+
+ /**
+ * Determine if the LogEvent should be processed or ignored.
+ *
+ * @param event The LogEvent.
+ * @return true if the LogEvent should be processed.
+ */
+ public boolean isFiltered(final LogEvent event) {
+ return filter != null && filter.filter(event) == Filter.Result.DENY;
+ }
+
+ private void beforeLogEvent() {
+ counter.incrementAndGet();
+ }
+
+ private void afterLogEvent() {
+ if (counter.decrementAndGet() == 0) {
+ signalCompletionIfShutdown();
+ }
+ }
+
+ private void signalCompletionIfShutdown() {
+ final Lock lock = shutdownLock;
+ lock.lock();
+ try {
+ if (shutdown.get()) {
+ noLogEvents.signalAll();
+ }
+ } finally {
+ lock.unlock();
+ }
+ }
+
+ private void afterLogEvent2() {
+ if (counter.decrementAndGet() == 0 && shutdown.get()) {
+ signalCompletionIfShutdown();
+ }
+ }
+
+ private void processLogEvent(final LogEvent event) {
+ event.setIncludeLocation(isIncludeLocation());
+ callAppenders(event);
+ logParent(event);
+ }
+
+ public boolean isIncludeLocation() {
+ return includeLocation;
+ }
+
+ private void logParent(final LogEvent event) {
+ if (additive && parent != null) {
+ parent.log(event);
+ }
+ }
+
+ protected void callAppenders(final LogEvent event) {
+ for (final AppenderControl control : appenderMap.values()) {
+ control.callAppender(event);
+ }
+ }
+
+}