1
NotFoundEgg 2023-10-22 21:11:55 +08:00 1
即使不打印日志,但如果涉及到字符串拼接或 toString 也会损耗性能,所有要不就判断,要不就占位符,不要使用“+”的方式拼接
不过实际写的时候我个人也很少在意这个 |
2
clickhouse 2023-10-22 21:13:22 +08:00 1
很简单,比如你 debug 打印一个对象的具体内容,不管你事 toString 也好,还是转 JSON 打印也好,这个方法都会被执行。而你不是 debug 级别,那么这个方法就白白消耗了系统的资源。
|
3
wdlth 2023-10-22 21:17:31 +08:00 1
因为用占位符的话,后续的参数还是需要经过执行的,不过大多时候参数是已经确定的值/引用,性能开销没这么大。
如果日志占位参数是较复杂的方法,加上 isDebugEnabled 跳过更好。 |
4
stinkytofu 2023-10-22 21:21:10 +08:00
@clickhouse #2 所以说 C/C++中的预编译的机制真的挺好的
|
5
vitoliu 2023-10-22 21:44:47 +08:00
目光向前看,debug 和 trace 日志都没有意义了。
因为已经有了 arthas 。 就像 Spring 之前 xml 、tomcat web.xml 配置也有一堆范式一样,现在谁还用啊? |
6
BraveXaiver OP @NotFoundEgg
@clickhouse @wdlth 谢谢,主要就是字符串格式化时,担心 toString 大 POJO 时带来的性能开销。但是即便以 jdk8 这样的老 JVM ,不要说 toString ,就算是调用 jackson 处理 1MB 不到的请求体,也是几乎不用担心性能开销的吧(若无高并发)。 换言之,如果确定程序中能遇到的 POJO json 化后最多也就 10-20 kb, debugEnabled 不查也没问题。 |
7
BBCCBB 2023-10-22 22:57:51 +08:00
方法调用要资源+时间.. 如果你 log.debug 的参数里有需要计算得到的结果, 那也要浪费资源..
比如 log.debug("{}", computeXXX()); 这个 computeXXX()需要耗费很多资源.. |
8
BBCCBB 2023-10-22 22:59:33 +08:00 1
10-20kb json 字符串已经是很大的开销了..
要养成好习惯. debug log 里有较大消耗, 比如非 xxx.getXX() 简单获取属性的操作, 都加上 log.isDebugEnable |
9
zsdroid 2023-10-23 09:05:40 +08:00
这简单,自己用 lambda 封装一下就解决这个问题了。
|
10
cloud107202 2023-10-23 09:26:19 +08:00
不加判断会带来额外的 Call by Value Evaluation 开销
高版本 slf4j 2.X ( spring boot3 的自动依赖) 有个 Fluent Logging API 能优雅解决这个问题(和因为强迫症希望少一组 if-block 引发心里不适的问题) |
11
oneisall8955 2023-10-23 09:26:48 +08:00 via Android
用对象包一层,tostring 在将源对象输出
|
12
aqua02 2023-10-23 11:00:54 +08:00 via Android
按计算机原理的角度来说,一个主频为 1ghz 执行一个机器指令 时间为 1/1g 秒, 又因为它是函数 那就加几个指令 当 4 条吧,又因为它是 java 封装 ,总指令数 x5 吧,时间就是 ( 4+1 )*5 / 1g 秒,忽略不计吧😂,1g=10^9 。 具体几条可以反编译看看。
|
13
Masoud2023 2023-10-23 13:39:05 +08:00
不是我非在这抬杠,一大堆第三方库开源组件也没非得在 log.debug 前面判断环境吧。
都考虑到这种性能损耗了,为什么不换其他的编译语言? 觉得不爽可以自己给 java 写个 babel ,打包的时候把 log.debug 全删了。 或者直接换个语言。 |
14
Aresxue 2023-10-23 14:04:33 +08:00
如果参数是已经计算好的变量判断不判断其实都还好,如果占位符的参数还涉及到比较吃 cpu 的计算最好还是判断下能节省点 cpu 。
|
15
oldshensheep 2023-10-23 16:02:16 +08:00 1
如果你看 log4j2 源码会发现实际上 log4j2 已经自动检查 log level 了,不会做无谓的调用。但是如果你手动拼接字符串 "log some %s some".formated(obj),这个损耗会大一些,因为会调用 obj.toString 。调用这样的 log 方法 (final String message, final Object... params),而不是手动拼接字符串。
还有一直情况就是做大量计算,这种情况可以使用,lambda ,()-> computeSome() 这种也是一样会检查后再调用 |
16
cnzjl 2023-10-23 16:03:58 +08:00
突然想到写一个编译插件,打包项目的时候判断下 log.debug()有没有被 if(log.isDebugEnable)包裹,没有的话就加上[绿帽 doge]
|