Java 中, logback 和 log4j2 日志工具,不使用 log.isDebugEnabled 判断就直接调用 debug 进行日志,在日志级别没有到 debug 的情况下,到底带来什么损失呢?

199 天前
 BraveXaiver
不加这个东西,我写着爽不说,代码整体看起来也更加美观。不知道大家是不是持相同看法。

所以我是真的很想不写,但又不知道这个到底为什么是约定俗成的最佳范式。

感谢任何分享和解答!
1789 次点击
所在节点    Java
16 条回复
NotFoundEgg
199 天前
即使不打印日志,但如果涉及到字符串拼接或 toString 也会损耗性能,所有要不就判断,要不就占位符,不要使用“+”的方式拼接

不过实际写的时候我个人也很少在意这个
clickhouse
199 天前
很简单,比如你 debug 打印一个对象的具体内容,不管你事 toString 也好,还是转 JSON 打印也好,这个方法都会被执行。而你不是 debug 级别,那么这个方法就白白消耗了系统的资源。
wdlth
199 天前
因为用占位符的话,后续的参数还是需要经过执行的,不过大多时候参数是已经确定的值/引用,性能开销没这么大。
如果日志占位参数是较复杂的方法,加上 isDebugEnabled 跳过更好。
stinkytofu
199 天前
@clickhouse #2 所以说 C/C++中的预编译的机制真的挺好的
vitoliu
199 天前
目光向前看,debug 和 trace 日志都没有意义了。
因为已经有了 arthas 。
就像 Spring 之前 xml 、tomcat web.xml 配置也有一堆范式一样,现在谁还用啊?
BraveXaiver
199 天前
@NotFoundEgg
@clickhouse
@wdlth

谢谢,主要就是字符串格式化时,担心 toString 大 POJO 时带来的性能开销。但是即便以 jdk8 这样的老 JVM ,不要说 toString ,就算是调用 jackson 处理 1MB 不到的请求体,也是几乎不用担心性能开销的吧(若无高并发)。

换言之,如果确定程序中能遇到的 POJO json 化后最多也就 10-20 kb, debugEnabled 不查也没问题。
BBCCBB
199 天前
方法调用要资源+时间.. 如果你 log.debug 的参数里有需要计算得到的结果, 那也要浪费资源..

比如
log.debug("{}", computeXXX());

这个 computeXXX()需要耗费很多资源..
BBCCBB
199 天前
10-20kb json 字符串已经是很大的开销了..

要养成好习惯. debug log 里有较大消耗, 比如非 xxx.getXX() 简单获取属性的操作, 都加上 log.isDebugEnable
zsdroid
199 天前
这简单,自己用 lambda 封装一下就解决这个问题了。
cloud107202
199 天前
不加判断会带来额外的 Call by Value Evaluation 开销


高版本 slf4j 2.X ( spring boot3 的自动依赖) 有个 Fluent Logging API 能优雅解决这个问题(和因为强迫症希望少一组 if-block 引发心里不适的问题)
oneisall8955
199 天前
用对象包一层,tostring 在将源对象输出
aqua02
199 天前
按计算机原理的角度来说,一个主频为 1ghz 执行一个机器指令 时间为 1/1g 秒, 又因为它是函数 那就加几个指令 当 4 条吧,又因为它是 java 封装 ,总指令数 x5 吧,时间就是 ( 4+1 )*5 / 1g 秒,忽略不计吧😂,1g=10^9 。 具体几条可以反编译看看。
Masoud2023
199 天前
不是我非在这抬杠,一大堆第三方库开源组件也没非得在 log.debug 前面判断环境吧。

都考虑到这种性能损耗了,为什么不换其他的编译语言?

觉得不爽可以自己给 java 写个 babel ,打包的时候把 log.debug 全删了。

或者直接换个语言。
Aresxue
199 天前
如果参数是已经计算好的变量判断不判断其实都还好,如果占位符的参数还涉及到比较吃 cpu 的计算最好还是判断下能节省点 cpu 。
oldshensheep
199 天前
如果你看 log4j2 源码会发现实际上 log4j2 已经自动检查 log level 了,不会做无谓的调用。但是如果你手动拼接字符串 "log some %s some".formated(obj),这个损耗会大一些,因为会调用 obj.toString 。调用这样的 log 方法 (final String message, final Object... params),而不是手动拼接字符串。

还有一直情况就是做大量计算,这种情况可以使用,lambda ,()-> computeSome() 这种也是一样会检查后再调用
cnzjl
199 天前
突然想到写一个编译插件,打包项目的时候判断下 log.debug()有没有被 if(log.isDebugEnable)包裹,没有的话就加上[绿帽 doge]

这是一个专为移动设备优化的页面(即为了让你能够在 Google 搜索结果里秒开这个页面),如果你希望参与 V2EX 社区的讨论,你可以继续到 V2EX 上打开本讨论主题的完整版本。

https://www.v2ex.com/t/984299

V2EX 是创意工作者们的社区,是一个分享自己正在做的有趣事物、交流想法,可以遇见新朋友甚至新机会的地方。

V2EX is a community of developers, designers and creative people.

© 2021 V2EX