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);
}
其中 charSequence
是 GString
个实例。
我添加了一些代码来检查性能:
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) }
我在 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);
}
其中 charSequence
是 GString
个实例。
我添加了一些代码来检查性能:
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) }