This is an automated email from the ASF dual-hosted git repository. pkarwasz pushed a commit to branch main in repository https://gitbox.apache.org/repos/asf/logging-log4j-transform.git
commit aa202dd830515aa9372668c0a77088c6e46f721e Author: Piotr P. Karwasz <[email protected]> AuthorDate: Tue May 2 18:14:23 2023 +0200 Add a LocationBenchmark --- log4j-transform-parent/pom.xml | 6 + log4j-transform-perf/pom.xml | 147 +++++++++++++++++++ .../logging/log4j/transform/perf/DemoAppender.java | 99 +++++++++++++ .../log4j/transform/perf/LocationBenchmark.java | 158 +++++++++++++++++++++ .../transform/perf/LocationLoggerCompiletime.java | 54 +++++++ .../transform/perf/LocationLoggerRuntime.java | 54 +++++++ .../src/main/resources/log4j2-demo.xml | 30 ++++ .../src/main/resources/log4j2-file.xml | 33 +++++ pom.xml | 1 + 9 files changed, 582 insertions(+) diff --git a/log4j-transform-parent/pom.xml b/log4j-transform-parent/pom.xml index 856c12d..268debc 100644 --- a/log4j-transform-parent/pom.xml +++ b/log4j-transform-parent/pom.xml @@ -41,6 +41,7 @@ <commons-logging.version>1.2</commons-logging.version> <commons-io.version>2.11.0</commons-io.version> <freemarker.version>2.3.32</freemarker.version> + <jmh.version>1.36</jmh.version> <junit.version>5.9.3</junit.version> <log4j2.version>2.20.0</log4j2.version> <maven.version>3.6.3</maven.version> @@ -104,6 +105,11 @@ <artifactId>freemarker</artifactId> <version>${freemarker.version}</version> </dependency> + <dependency> + <groupId>org.openjdk.jmh</groupId> + <artifactId>jmh-core</artifactId> + <version>${jmh.version}</version> + </dependency> <dependency> <groupId>org.apache.maven</groupId> <artifactId>maven-core</artifactId> diff --git a/log4j-transform-perf/pom.xml b/log4j-transform-perf/pom.xml new file mode 100644 index 0000000..dde286c --- /dev/null +++ b/log4j-transform-perf/pom.xml @@ -0,0 +1,147 @@ +<?xml version="1.0" encoding="UTF-8"?> +<!-- + ~ 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. + --> +<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 https://maven.apache.org/xsd/maven-4.0.0.xsd"> + <modelVersion>4.0.0</modelVersion> + <parent> + <groupId>org.apache.logging.log4j</groupId> + <artifactId>log4j-transform-parent</artifactId> + <version>${revision}</version> + <relativePath>../log4j-transform-parent</relativePath> + </parent> + <artifactId>log4j-transform-perf</artifactId> + <name>Log4j Transformation Tools Performance test</name> + <description>Performance tests for Apache Log4j Transformation Tools</description> + <properties> + <install.skip>true</install.skip> + <deploy.skip>true</deploy.skip> + <spotbugs.skip>true</spotbugs.skip> + </properties> + <dependencies> + <dependency> + <groupId>org.openjdk.jmh</groupId> + <artifactId>jmh-core</artifactId> + </dependency> + <dependency> + <groupId>org.apache.logging.log4j</groupId> + <artifactId>log4j-api</artifactId> + </dependency> + <dependency> + <groupId>org.apache.logging.log4j</groupId> + <artifactId>log4j-core</artifactId> + </dependency> + <dependency> + <groupId>com.github.spotbugs</groupId> + <artifactId>spotbugs-annotations</artifactId> + <scope>provided</scope> + </dependency> + </dependencies> + <build> + <plugins> + <plugin> + <groupId>org.apache.logging.log4j</groupId> + <artifactId>log4j-transform-maven-plugin</artifactId> + <executions> + <execution> + <goals> + <goal>process-classes</goal> + </goals> + <configuration> + <includes> + <include>**/*Compiletime.class</include> + </includes> + </configuration> + </execution> + </executions> + </plugin> + <plugin> + <groupId>org.apache.maven.plugins</groupId> + <artifactId>maven-compiler-plugin</artifactId> + <executions> + <execution> + <id>default-compile</id> + <configuration> + <annotationProcessorPaths combine.children="append"> + <path> + <groupId>org.openjdk.jmh</groupId> + <artifactId>jmh-generator-annprocess</artifactId> + <version>${jmh.version}</version> + </path> + <path> + <groupId>org.apache.logging.log4j</groupId> + <artifactId>log4j-core</artifactId> + <version>${log4j2.version}</version> + </path> + </annotationProcessorPaths> + </configuration> + </execution> + </executions> + </plugin> + <plugin> + <groupId>org.apache.maven.plugins</groupId> + <artifactId>maven-shade-plugin</artifactId> + <dependencies> + <dependency> + <groupId>org.apache.logging.log4j</groupId> + <artifactId>log4j-transform-maven-shade-plugin-extensions</artifactId> + <version>${project.version}</version> + </dependency> + </dependencies> + <executions> + <execution> + <goals> + <goal>shade</goal> + </goals> + <phase>package</phase> + <configuration> + <createDependencyReducedPom>false</createDependencyReducedPom> + <minimizeJar>false</minimizeJar> + <transformers> + <transformer implementation="org.apache.maven.plugins.shade.resource.ApacheLicenseResourceTransformer" /> + <transformer implementation="org.apache.maven.plugins.shade.resource.ApacheNoticeResourceTransformer" /> + <transformer implementation="org.apache.maven.plugins.shade.resource.ManifestResourceTransformer"> + <mainClass>org.openjdk.jmh.Main</mainClass> + <manifestEntries> + <Multi-Release>true</Multi-Release> + </manifestEntries> + </transformer> + <transformer implementation="org.apache.maven.plugins.shade.resource.ServicesResourceTransformer" /> + <transformer implementation="org.apache.logging.log4j.maven.plugins.shade.transformer.Log4j2PluginCacheFileTransformer" /> + </transformers> + <filters> + <filter> + <!-- + Shading signed JARs will fail without this. + http://stackoverflow.com/questions/999489/invalid-signature-file-when-attempting-to-run-a-jar + --> + <artifact>*:*</artifact> + <excludes> + <exclude>META-INF/DEPENDENCIES</exclude> + <exclude>META-INF/MANIFEST.MF</exclude> + <exclude>META-INF/*.SF</exclude> + <exclude>META-INF/*.DSA</exclude> + <exclude>META-INF/*.RSA</exclude> + </excludes> + </filter> + </filters> + </configuration> + </execution> + </executions> + </plugin> + </plugins> + </build> +</project> diff --git a/log4j-transform-perf/src/main/java/org/apache/logging/log4j/transform/perf/DemoAppender.java b/log4j-transform-perf/src/main/java/org/apache/logging/log4j/transform/perf/DemoAppender.java new file mode 100644 index 0000000..633a3ab --- /dev/null +++ b/log4j-transform-perf/src/main/java/org/apache/logging/log4j/transform/perf/DemoAppender.java @@ -0,0 +1,99 @@ +/* + * 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.transform.perf; + +import java.nio.ByteBuffer; + +import org.apache.logging.log4j.core.Appender; +import org.apache.logging.log4j.core.Core; +import org.apache.logging.log4j.core.Layout; +import org.apache.logging.log4j.core.LogEvent; +import org.apache.logging.log4j.core.appender.AbstractAppender; +import org.apache.logging.log4j.core.config.Property; +import org.apache.logging.log4j.core.config.plugins.Plugin; +import org.apache.logging.log4j.core.config.plugins.PluginAttribute; +import org.apache.logging.log4j.core.config.plugins.PluginElement; +import org.apache.logging.log4j.core.config.plugins.PluginFactory; +import org.apache.logging.log4j.core.layout.ByteBufferDestination; +import org.apache.logging.log4j.core.layout.ByteBufferDestinationHelper; +import org.apache.logging.log4j.core.util.Constants; + +/** + * An Appender that ignores log events but formats + */ +@Plugin(name = DemoAppender.PLUGIN_NAME, category = Core.CATEGORY_NAME, elementType = Appender.ELEMENT_TYPE, printObject = true) +public class DemoAppender extends AbstractAppender implements ByteBufferDestination { + + public static final String PLUGIN_NAME = "Demo"; + + private final ByteBuffer byteBuffer = ByteBuffer.wrap(new byte[4096]); + public long checksum; + + @PluginFactory + public static DemoAppender createAppender( + @PluginAttribute(value = "name", defaultString = "DEMO") final String name, + @PluginElement("Layout") final Layout<?> layout) { + return new DemoAppender(name, layout); + } + + private DemoAppender(final String name, final Layout<?> layout) { + super(name, null, layout, true, Property.EMPTY_ARRAY); + } + + @Override + public void append(final LogEvent event) { + if (Constants.ENABLE_DIRECT_ENCODERS) { + getLayout().encode(event, this); + drain(byteBuffer); + } else { + final byte[] binary = getLayout().toByteArray(event); + consume(binary, 0, binary.length); + } + } + + @Override + public ByteBuffer getByteBuffer() { + return byteBuffer; + } + + @Override + public ByteBuffer drain(final ByteBuffer buf) { + buf.flip(); + consume(buf.array(), buf.position(), buf.limit()); + buf.clear(); + return buf; + } + + @Override + public void writeBytes(final ByteBuffer data) { + ByteBufferDestinationHelper.writeToUnsynchronized(data, this); + } + + @Override + public void writeBytes(final byte[] data, final int offset, final int length) { + ByteBufferDestinationHelper.writeToUnsynchronized(data, offset, length, this); + } + + private void consume(final byte[] data, final int offset, final int length) { + // need to do something with the result or the JVM may optimize everything away + long sum = 0; + for (int i = offset; i < length; i++) { + sum += data[i]; + } + checksum += sum; + } +} diff --git a/log4j-transform-perf/src/main/java/org/apache/logging/log4j/transform/perf/LocationBenchmark.java b/log4j-transform-perf/src/main/java/org/apache/logging/log4j/transform/perf/LocationBenchmark.java new file mode 100644 index 0000000..e4e710b --- /dev/null +++ b/log4j-transform-perf/src/main/java/org/apache/logging/log4j/transform/perf/LocationBenchmark.java @@ -0,0 +1,158 @@ +/* + * 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.transform.perf; + +import java.io.IOException; +import java.nio.file.Files; +import java.nio.file.Path; +import java.nio.file.Paths; +import java.util.concurrent.TimeUnit; + +import edu.umd.cs.findbugs.annotations.SuppressFBWarnings; +import org.apache.logging.log4j.LogBuilder; +import org.apache.logging.log4j.LogManager; +import org.apache.logging.log4j.Logger; +import org.apache.logging.log4j.Marker; +import org.apache.logging.log4j.MarkerManager; +import org.openjdk.jmh.annotations.Benchmark; +import org.openjdk.jmh.annotations.BenchmarkMode; +import org.openjdk.jmh.annotations.Mode; +import org.openjdk.jmh.annotations.OutputTimeUnit; +import org.openjdk.jmh.annotations.Param; +import org.openjdk.jmh.annotations.Scope; +import org.openjdk.jmh.annotations.Setup; +import org.openjdk.jmh.annotations.State; +import org.openjdk.jmh.annotations.TearDown; + +/** + * <p> + * Compares {@link Logger} and {@link LogBuilder} before and after + * postprocessing by log4j-weaver. + * </p> + * <h2>HOW TO RUN THIS TEST</h2> + * <ul> + * <li>single thread: + * + * <pre> + * java -jar target/benchmarks.jar ".*LocationBenchmark*" + * </pre> + * + * </li> + * <li>multiple threads (for example, 4 threads): + * + * <pre> + * java -jar target/benchmarks.jar ".*LocationBenchmark.*" -t 4 + * </pre> + * + * </li> + * </ul> + * + * <h2>AVAILABLE PARAMETERS</h2> The following parameters are available: + * <ul> + * <li>{@code fileName}, uses the give file name instead of the default + * "target/benchmark.log". E.g.: + * + * <pre> + * java -jar target/benchmarks.jar ".*LocationBenchmark*" -p fileName=/dev/null + * </pre> + * + * </li> + * <li>{@code useDemoAppender}, uses a demo appender that performs all appender + * actions, except actually writing to a stream.</li> + * </ul> + */ +@State(Scope.Benchmark) +@BenchmarkMode(Mode.Throughput) +@OutputTimeUnit(TimeUnit.SECONDS) +public class LocationBenchmark { + + @Param("target/benchmark.log") + private String fileName; + + @Param("false") + private boolean useDemoAppender; + + private Marker marker; + private Logger logger; + private LocationLoggerRuntime runtime; + private LocationLoggerCompiletime compiletime; + + @Setup + public void setUp() { + if (useDemoAppender) { + System.setProperty("log4j2.configurationFile", "log4j2-demo.xml"); + } else { + System.setProperty("log4j2.configurationFile", "log4j2-file.xml"); + System.setProperty("LOG_FILE", fileName); + } + logger = LogManager.getLogger(getClass()); + marker = MarkerManager.getMarker("TestMarker"); + runtime = new LocationLoggerRuntime(logger, marker); + compiletime = new LocationLoggerCompiletime(logger, marker); + } + + @TearDown + @SuppressFBWarnings("PATH_TRAVERSAL_IN") + public void tearDown() throws IOException { + System.clearProperty("log4j2.configurationFile"); + LogManager.shutdown(); + Path filePath = Paths.get(fileName); + if (Files.isRegularFile(filePath)) { + Files.deleteIfExists(filePath); + } + } + + @Benchmark + public void runtimeLogNoMarker() { + runtime.logNoMarker(); + } + + @Benchmark + public void runtimeLogMarker() { + runtime.logMarker(); + } + + @Benchmark + public void runtimeLogBuilderNoMarker() { + runtime.logBuilderNoMarker(); + } + + @Benchmark + public void runtimeLogBuilderMarker() { + runtime.logBuilderMarker(); + } + + @Benchmark + public void compiletimeLogNoMarker() { + compiletime.logNoMarker(); + } + + @Benchmark + public void compiletimeLogMarker() { + compiletime.logMarker(); + } + + @Benchmark + public void compiletimeLogBuilderNoMarker() { + compiletime.logBuilderNoMarker(); + } + + @Benchmark + public void compiletimeLogBuilderMarker() { + compiletime.logBuilderMarker(); + } +} diff --git a/log4j-transform-perf/src/main/java/org/apache/logging/log4j/transform/perf/LocationLoggerCompiletime.java b/log4j-transform-perf/src/main/java/org/apache/logging/log4j/transform/perf/LocationLoggerCompiletime.java new file mode 100644 index 0000000..7ff3ad1 --- /dev/null +++ b/log4j-transform-perf/src/main/java/org/apache/logging/log4j/transform/perf/LocationLoggerCompiletime.java @@ -0,0 +1,54 @@ +/* + * 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.transform.perf; + +import edu.umd.cs.findbugs.annotations.SuppressFBWarnings; +import org.apache.logging.log4j.Logger; +import org.apache.logging.log4j.Marker; + +/** + * Should be identical to {@link LocationLoggerRuntime}. + * + */ +public class LocationLoggerCompiletime { + + private static final String MESSAGE = "Compiletime location"; + private final Logger logger; + private final Marker marker; + + @SuppressFBWarnings("EI_EXPOSE_REP2") + public LocationLoggerCompiletime(final Logger logger, final Marker marker) { + this.logger = logger; + this.marker = marker; + } + + public void logNoMarker() { + logger.info(MESSAGE); + } + + public void logMarker() { + logger.info(marker, MESSAGE); + } + + public void logBuilderNoMarker() { + logger.atInfo().log(MESSAGE); + } + + public void logBuilderMarker() { + logger.atInfo().withMarker(marker).log(MESSAGE); + } +} diff --git a/log4j-transform-perf/src/main/java/org/apache/logging/log4j/transform/perf/LocationLoggerRuntime.java b/log4j-transform-perf/src/main/java/org/apache/logging/log4j/transform/perf/LocationLoggerRuntime.java new file mode 100644 index 0000000..9ef94f4 --- /dev/null +++ b/log4j-transform-perf/src/main/java/org/apache/logging/log4j/transform/perf/LocationLoggerRuntime.java @@ -0,0 +1,54 @@ +/* + * 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.transform.perf; + +import edu.umd.cs.findbugs.annotations.SuppressFBWarnings; +import org.apache.logging.log4j.Logger; +import org.apache.logging.log4j.Marker; + +/** + * Should be identical to {@link LocationLoggerCompiletime}. + * + */ +public class LocationLoggerRuntime { + + private static final String MESSAGE = "Runtime location"; + private final Logger logger; + private final Marker marker; + + @SuppressFBWarnings("EI_EXPOSE_REP2") + public LocationLoggerRuntime(final Logger logger, final Marker marker) { + this.logger = logger; + this.marker = marker; + } + + public void logNoMarker() { + logger.info(MESSAGE); + } + + public void logMarker() { + logger.info(marker, MESSAGE); + } + + public void logBuilderNoMarker() { + logger.atInfo().log(MESSAGE); + } + + public void logBuilderMarker() { + logger.atInfo().withMarker(marker).log(MESSAGE); + } +} diff --git a/log4j-transform-perf/src/main/resources/log4j2-demo.xml b/log4j-transform-perf/src/main/resources/log4j2-demo.xml new file mode 100644 index 0000000..456d944 --- /dev/null +++ b/log4j-transform-perf/src/main/resources/log4j2-demo.xml @@ -0,0 +1,30 @@ +<?xml version="1.0" encoding="UTF-8"?> +<!-- + ~ 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. + --> +<Configuration status="INFO"> + <Appenders> + <Demo name="DEMO"> + <!-- Must include location --> + <PatternLayout pattern="%d [%-5p] %l: %m"/> + </Demo> + </Appenders> + <Loggers> + <Root level="DEBUG"> + <AppenderRef ref="DEMO"/> + </Root> + </Loggers> +</Configuration> diff --git a/log4j-transform-perf/src/main/resources/log4j2-file.xml b/log4j-transform-perf/src/main/resources/log4j2-file.xml new file mode 100644 index 0000000..7c9d98c --- /dev/null +++ b/log4j-transform-perf/src/main/resources/log4j2-file.xml @@ -0,0 +1,33 @@ +<?xml version="1.0" encoding="UTF-8"?> +<!-- + ~ 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. + --> +<Configuration status="INFO"> +<Properties> + <Property name="LOG_FILE" value="target/benchmark.log"/> +</Properties> + <Appenders> + <!-- Must include location --> + <File name="FILE" fileName="${sys:LOG_FILE}"> + <PatternLayout pattern="%d [%-5p] %l: %m"/> + </File> + </Appenders> + <Loggers> + <Root level="DEBUG"> + <AppenderRef ref="FILE"/> + </Root> + </Loggers> +</Configuration> diff --git a/pom.xml b/pom.xml index 06c9492..4cdc39a 100644 --- a/pom.xml +++ b/pom.xml @@ -63,6 +63,7 @@ <!-- the parent POM must come first: --> <module>log4j-transform-parent</module> <module>log4j-transform-maven-plugin</module> + <module>log4j-transform-perf</module> <module>log4j-weaver</module> <module>log4j-transform-maven-shade-plugin-extensions</module> </modules>
