Java 如何为自定义日志解决方案正确创建性能测试?

Java 如何为自定义日志解决方案正确创建性能测试?,java,logging,performance-testing,benchmarking,jmh,Java,Logging,Performance Testing,Benchmarking,Jmh,在工作中,我主动从头开始创建一个日志库,用于内部服务和项目 到目前为止,我已经用一个自定义类创建了一个概念证明,该类扩展了PatternLayout,并模糊了输出日志条目中的某些字段 现在的主要任务是断言性能是可以接受的,我的解决方案可以处理数百万个日志条目,而不会丢失消息 我决定为我的自定义logback、默认logback布局和Log4j2编写性能测试,以便比较输出结果。 我使用jmh进行了单元测试 <?xml version="1.0" encoding="UTF-8"?> &

在工作中,我主动从头开始创建一个日志库,用于内部服务和项目

到目前为止,我已经用一个自定义类创建了一个概念证明,该类扩展了PatternLayout,并模糊了输出日志条目中的某些字段

现在的主要任务是断言性能是可以接受的,我的解决方案可以处理数百万个日志条目,而不会丢失消息

我决定为我的自定义logback、默认logback布局和Log4j2编写性能测试,以便比较输出结果。 我使用
jmh
进行了单元测试

<?xml version="1.0" encoding="UTF-8"?>
<configuration>

    <appender name="FILE_APPLY_RULES" class="ch.qos.logback.core.FileAppender">
        <file>logs\log.txt</file>
        <encoder class="ch.qos.logback.core.encoder.LayoutWrappingEncoder">
            <layout class="com.ingenico.epayments.logging.rule.LoggingRulesApplicator">
                <pattern>%msg%n</pattern>
                <applyRules>true</applyRules>
                <loggingRules>src/test/resources/logging-rules.json</loggingRules>
            </layout>
        </encoder>
    </appender>

    <appender name="ASYNC_FILE_APPLY_RULES" class="ch.qos.logback.classic.AsyncAppender">
        <discardingThreshold>0</discardingThreshold>
        <appender-ref ref="FILE_APPLY_RULES" />
        <queueSize>256</queueSize>
        <includeCallerData>false</includeCallerData>
        <neverBlock>true</neverBlock>
    </appender>

    <root level="INFO">
        <appender-ref ref="ASYNC_FILE_APPLY_RULES" />
    </root>

</configuration>

@Slf4j
public class LogbackTest {

    @Test
    public void launchBenchmark() throws RunnerException {
        Options opt = new OptionsBuilder()
                .include(this.getClass().getName() + ".*")
                .timeUnit(TimeUnit.MICROSECONDS)
                .warmupTime(TimeValue.seconds(1))
                .warmupIterations(2)
                .measurementTime(TimeValue.seconds(1))
                .measurementIterations(2)
                .threads(2)
                .forks(1)
                .shouldFailOnError(true)
                .shouldDoGC(true)
                .addProfiler(StackProfiler.class)
                .addProfiler(HotspotRuntimeProfiler.class)
                .build();
        new Runner(opt).run();
    }

    @BenchmarkMode(Mode.All)
    @Measurement(iterations = 200, time = 200, timeUnit = MILLISECONDS)
    @Benchmark
    public void logBenchmark() {
        log.info("{\"id\":\"12345\",\"cardData\":{\"bar\":\"bar\",\"foo\":\"foo\",\"number\":\"number\"}}");
    }

}

logs\log.txt
%消息%n
真的
src/test/resources/logging-rules.json
0
256
假的
真的
@Slf4j
公共类LogbackTest{
@试验
public void launchBenchmark()引发RunnerException{
Options opt=新选项生成器()
.include(this.getClass().getName()+“*”)
.时间单位(时间单位.微秒)
.预热时间(时间值.秒(1))
.预热操作(2)
.测量时间(时间值.秒(1))
.测量(2)
.螺纹(2)
.福克斯(1)
.shouldFaildOnError(正确)
.shouldDoGC(正确)
.addProfiler(StackProfiler.class)
.addProfiler(HotspotRuntimeProfiler.class)
.build();
new Runner(opt.run();
}
@基准模式(Mode.All)
@测量(迭代次数=200,时间=200,时间单位=毫秒)
@基准
公共基准{
log.info(“{\“id\”:“12345\”,“cardData\”:{\“bar\”:“bar\”,“foo\”:“foo\”,“number\”:“number\”}”);
}
}
测试正在运行,在输出中,我看到了很多结果数字,但我不知道应该比较哪些值,我如何断言,如果我有良好的性能结果,那不是因为消息被删除了


您能告诉我如何准备有效的性能测试吗?

您有一个异步
asynchronousappender
appender,它可能会删除队列中的消息。与此同时,JMH基准测试希望同步执行
@benchmark
注释方法中的代码,以计算所需的时间。这行不通

在我看来,您试图一次测试太多的东西,例如整个Logback堆栈。如果您开发了一个自定义布局类
LoggingRulesApplicationor
,那么首先为这个类编写一个JMH bechmark


看一看。通过使用NOOP appender,那里的设置得到了简化。您可能也应该使用NOOP appender。

你好,卡罗尔,谢谢,我更新了我的问题。我知道我无法摆脱这种下降,但我如何才能断言良好的绩效结果不是因为下降。我还认为,必须有一种方法来比较日志记录,就像您试图编写一个端到端的基准测试,以证明您的解决方案可以达到理想的SLA水平。为代码片段(例如布局)编写微基准测试,或者在目标服务器上启用日志记录,对应用程序执行完整的端到端性能测试。