在传递多个字符串进行日志记录时,最好是使用varargs还是字符串连接?
生产环境中将禁用日志记录。
考虑以下代码,
public void log(int logLevel, String ... msg) {
if (logLevel >= currentLogLevel) {
for (String m : msg) {
// print the log to file
}
}
}
// calling
log(2, "text1", var1, "text2");
Vs以上。
public void log(int logLevel, String msg) {
if (logLevel >= currentLogLevel) {
// print the log to file
}
}
// calling
log(2, "text1" + var1 + "text2");
哪一个在两种情况下都有效(启用/禁用)?
答案 0 :(得分:7)
其中任何一项都表现不佳。 varargs会表现得更好,因为它没有进行String
连接,这是一个比数组创建更昂贵的操作,但是因为你使用String
varargs而不是Object
varargs,toString()
方法必须在即使在生产的所有对象上调用,这将相对昂贵。
然而,不要害怕!这是已解决的问题。 SLF4J (Simple Logging Facade for Java)已经找到了最适合你的方法。如果您使用SLF4J实现(最常见的两个是Log4J和Logback),则可以使用parameterized logging arguments:
更好的选择
基于消息格式存在一种方便的替代方案。假设entry是一个对象,你可以写:
Object entry = new SomeObject(); logger.debug("The entry is {}.", entry);
只有在评估是否记录后,并且只有在决定是肯定的情况下,记录器实现才会格式化消息并替换' {}'与条目的字符串值配对。换句话说,当禁用日志语句时,此表单不会产生参数构造的成本。
以下两行将产生完全相同的输出。但是,如果禁用日志记录语句,则第二个变体将比第一个变体的性能优于至少30个。
logger.debug("The new entry is "+entry+"."); logger.debug("The new entry is {}.", entry);
也可以使用两个参数变体。例如,您可以写:
logger.debug("The new entry is {}. It replaces {}.", entry, oldEntry);
如果需要传递三个或更多参数,则还可以使用Object []变体。例如,您可以写:
Object[] paramArray = {newVal, below, above}; logger.debug("Value {} was inserted between {} and {}.", paramArray);
请注意,在第一种和第二种情况下,它不会创建临时数组,如果在SLF4J中不需要,则方法签名不存在创建数组。 { {3}}
如果您决定使用Logback
,您应该知道关闭日志时的方法调用的成本约为20纳秒。 Here is the full documentation where you can see all the different method signatures:
您可以通过将根记录程序的级别设置为Level.OFF(最高级别)来完全关闭日志记录。完全关闭日志记录时,日志请求的成本包括方法调用和整数比较。在3.2Ghz Pentium D机器上,此成本通常约为20纳秒。
答案 1 :(得分:1)
从Java-8开始,使用%JAVA_HOME%\jre\lib\security\cacerts
的替代方案更快:
Supplier<String>
这比串联快得多,前提是你多次执行此行(第一次因为应该创建匿名类而慢)。来源:AlekseyShipilëvtalk on Joker'14(PDF,查看幻灯片26-28)。
答案 2 :(得分:0)