Groovy StringBuilder 附加 GString 性能问题

Groovy StringBuilder append GString performance issue

我在 log4j2 日志记录方面遇到问题。

(groovy-all 4.0.0, org.apache.logging.log4j 2.17.1, gmavenplus-plugin 1.13.0)

我有一个很大的嵌套地图对象(10 个键和一个值是一个 100 长的地图列表)。

我这样称呼日志:

Map myNestedMap = (1..1500).collectEntries{ ["key-$it", "value-$it"] }
log.debug("Some message, $myNestedMap")

这条线有效 10+ 秒...

调试时我发现调用了:

//org.apache.logging.log4j.message.ReusableSimpleMessage

@Override
public void formatTo(final StringBuilder buffer) {
    buffer.append(charSequence);
}

其中 charSequenceGString 个实例。

我添加了一些代码来检查性能:

Map myNestedMap = ...

Closure measure = { String message,  Closure cl ->
    long start = Calendar.getInstance().getTimeInMillis()
    cl.call()
    long end = Calendar.getInstance().getTimeInMillis()
    println("$message ${(end-start)/1000} sec")
}
measure('StringBuilder:(GString, but no cast)') {
    new StringBuilder().append("$myNestedMap")
}

measure('StringBuilder:(cast to String)') {
    new StringBuilder().append((String)"$myNestedMap")
}
measure('StringBuilder:(cast to CharSequence)') {
    new StringBuilder().append((CharSequence)"$myNestedMap")
}
measure('StringBuilder:(cast to GString)') {
    new StringBuilder().append((GString)"$myNestedMap")
}

输出:

StringBuilder:(GString, but no cast) 0.354 sec
StringBuilder:(cast to String) 0.296 sec
StringBuilder:(cast to CharSequence) 13.479 sec
StringBuilder:(cast to GString) 12.937 sec

所以我想就如何处理这个问题寻求一些建议。

我能做到:

Map myNestedMap = ...
log.debug("Some message, $myNestedMap" as String)

但我不想将整个项目中的所有日志记录都转换为String。

您可以扩展您的记录器并覆盖调试和其他记录方法。

或使用元类重新定义GString

的方法

在项目初始化时执行一次:

Logger.metaClass.debug = {GString s-> delegate.debug(s as String) }