java日志格式应该是占位符还是字符串拼接

史亚健      2022-04-22     747

关键词:

背景

​ 上次在群中,有个群友说自己把所有项目中,所有使用占位符打印日志的方式都修改成为了字符串拼接的方式,因为他曾经看了一篇文章,说字符串拼接的形式比占位符形式的性能更好,这个话题引起了大家的广泛讨论。

​ 在我印象中,我记得曾经看过的文章说,占位符的方式性能好,因为如果不打日志的话,就不会进行字符串拼接,节省性能。最后抱着一探究竟的心态,我进行了一次日志输出方式的实验。

工具

IDEA + Gradle + JDK 8 + SpringBoot + Junit + Slf4j + logback

测试方式

本次测试我定义了4个方法,每个方法同时打印 DEBUG ,INFO 日志,默认日志级别是INFO级别的,所有DEBUG级别日志是不输出的,这样可以检测输出的日志会不会被不输出级别日志影响,同时我还给部分方法增加了if判断,这个是为了测试,我们是否有必要显性的进行日志级别的操作,具体代码如下:

 public void record(LogEntity logEntity) {
        for (int i = 0; i < 1000; i++) {
            if (log.isDebugEnabled()) {
                log.debug("id:{},name:{},ip:{},url:{},params:{}",
                        logEntity.getId(),
                        logEntity.getName(),
                        logEntity.getId(),
                        logEntity.getUrl(),
                        logEntity.getParams());
            }
            log.info("id:{},name:{},ip:{},url:{},params:{}",
                    logEntity.getId(),
                    logEntity.getName(),
                    logEntity.getId(),
                    logEntity.getUrl(),
                    logEntity.getParams());
        }
    }

    public void record1(LogEntity logEntity) {
        for (int i = 0; i < 1000; i++) {
            log.debug("id:{},name:{},ip:{},url:{},params:{}",
                    logEntity.getId(),
                    logEntity.getName(),
                    logEntity.getId(),
                    logEntity.getUrl(),
                    logEntity.getParams());
            log.info("id:{},name:{},ip:{},url:{},params:{}",
                    logEntity.getId(),
                    logEntity.getName(),
                    logEntity.getId(),
                    logEntity.getUrl(),
                    logEntity.getParams());
        }
    }

    public void record2(LogEntity logEntity) {
        for (int i = 0; i < 1000; i++) {
            if (log.isDebugEnabled()) {
                log.debug("id:" + logEntity.getId() +
                        ",name:" + logEntity.getName() +
                        ",ip:" + logEntity.getId() +
                        ",url:" + logEntity.getUrl() +
                        ",params:" + logEntity.getParams());
            }
            log.info("id:" + logEntity.getId() +
                    ",name:" + logEntity.getName() +
                    ",ip:" + logEntity.getId() +
                    ",url:" + logEntity.getUrl() +
                    ",params:" + logEntity.getParams());

        }
    }

    public void record3(LogEntity logEntity) {
        for (int i = 0; i < 1000; i++) {
            log.debug("id:" + logEntity.getId() +
                      ",name:" + logEntity.getName() +
                      ",ip:" + logEntity.getId() +
                      ",url:" + logEntity.getUrl() +
                      ",params:" + logEntity.getParams());
            log.info("id:" + logEntity.getId() +
                    ",name:" + logEntity.getName() +
                    ",ip:" + logEntity.getId() +
                    ",url:" + logEntity.getUrl() +
                    ",params:" + logEntity.getParams());

        }
    }

测试结果

我运行了6次Junit测试用例,结果如下:

结论

通过测试结果可以有以下发现:

字符串拼接的方法,大部分下情况性能高于占位符

如果采用占位符的方式,一定不要增加 log.isDebugEnabled()这种方式再显性的进行判断,否则性能会大大降低

昨天看到nacos项目,在翻看nacos源码的时候,发现针对日志输出这块,nacos也使用的字符串拼接

本文没有太高深的道理和原理,只是因为一个小的讨论,进行了一次实验,实验的过程和结果是否准确可靠还需要大家各自斟酌,同时希望借此抛砖引玉,能有大神给更加详细的解答。

github地址: https://github.com/Shiyajian/examples ,查看 spring-boot/chapter1/log

其他

自己写了个插件,可以打开CSDN的博客之后,自动展开全部内容,不用每次点【查看更多】,然后还需要登录那么麻烦了,github: https://github.com/Shiyajian/CSDN-clear.git

个人QQ好友群:757696438,吹牛扯淡为主,技术为辅,拒绝装逼,最欢迎妹子。
个人微信:q408859832 技术交流为主
备注:博客园

如果我想放置占位符,DW 日期映射中的日期字段应该是日期数据类型还是字符串数据类型?

...位符,DW日期映射中的日期字段应该是日期数据类型还是字符串数据类型?【英文标题】:ShoulddatefieldinDWdate-mapbeofDatedatatypeorofStringdatatype,ifIwanttoputplaceholders?【发布时间】:2014-11-1105:30:52【问题描述】:和其他所有数据仓库一样... 查看详情

占位符与拼接符的区别——2017.08.16

...是POJO对象的属性    拼接符:¥{  }字符串原样拼接,1如果传 查看详情

对trace/debug/info级别的日志输出必须使用条件输出形式或者使用占位符的方式

...bol);如果日志级别是warn,上述日志不会打印,但是会执行字符串拼接操作,如果symbol是对象,会执行toString()方法,浪费了系统资源,执行了上述操作,最终日志却没有打印。正例:(条件)建设采用如下方式if(logger.isDebugEnabled()... 查看详情

对trace/debug/info级别的日志输出必须使用条件输出形式或者使用占位符的方式

...bol);如果日志级别是warn,上述日志不会打印,但是会执行字符串拼接操作,如果symbol是对象,会执行toString()方法,浪费了系统资源,执行了上述操作,最终日志却没有打印。正 查看详情

c语言格式控制符/占位符

...面的文章中也介绍了C语言中变量类型有整形、浮点数、字符串、数组……实际上他们都有各自对应的占位符!%d:用来输出有符号的十进 查看详情

javascript以指定的字符串格式化某字符串的占位符

目前为止Javascript进行字符串拼接只能以基本语法形式进行,而.NETFramework提供了许多种对字符串的简便操作方法,下面这个用于Javascript的方法类似于.NETC#中的string.Format方法,可以格式化数字占位符://以指定的对象格式化某字符... 查看详情

如何在 Java 中使用占位符进行字符串格式化(如在 Python 中)?

】如何在Java中使用占位符进行字符串格式化(如在Python中)?【英文标题】:HowtodostringformattingwithplaceholdersinJava(likeinPython)?【发布时间】:2013-07-0609:50:09【问题描述】:我是Java新手,来自Python。在Python中,我们像这样进行字符... 查看详情

lua中string.format占位符的使用(代码片段)

虽然lua中字符串拼接“string.format”相对于“..”消耗较大,但有时为了代码的可读性,项目中还是经常用到“string.format”。至于这两个用法的性能看源码也很容易看出来,这里就简单说一下,前者其实调用C函数str_format来实现拼... 查看详情

详解python拼接字符串的七种方式(代码片段)

...牛调侃,他说程序员每天就做两件事,其中之一就是处理字符串。相信不少同学会有同感。几乎任何一种编程语言,都把字符串列为最基础和不可或缺的数据类型。而拼接字符串是必备的一种技能。今天,我跟大家一起来学习Pyt... 查看详情

如何在 Android 中将格式化字符串与占位符一起使用?

】如何在Android中将格式化字符串与占位符一起使用?【英文标题】:HowtouseformattedstringstogetherwithplaceholdersinAndroid?【发布时间】:2014-06-2314:16:22【问题描述】:在Android中可以在字符串中使用占位符,例如:<stringname="number">Myn... 查看详情

Java:“$1”是占位符吗? [复制]

...习:将camelCase写作分解成单词,例如输入“camelCaseTest”应该给出输出“camelCaseTest”。我在网上找到了这个解决方案,但我不明白它的全部publicstaticStringcam 查看详情

Osgi 属性占位符

...布时间】:2017-03-2119:16:36【问题描述】:我这里只能使用字符串绑定,enableRequestValidation应该始终是字符串,放入我想要使用布尔值的bean,如何使用属性占位符绑定来实现?<property-placeholderpersistent-id="JsonValidator"update-strategy="re 查看详情

go语言基础:语言格式|变量|常量|数据类型|占位符|转义符(代码片段)

...型数字字面量语法(Numberliteralssyntax)浮点型和复数布尔值字符串字符串转义符多行字符串字符串操作byte和rune类型修改字符串类型转换%占位符一般占位符布尔占位符整数占位符浮点数和复数占位符 查看详情

go语言基础:语言格式|变量|常量|数据类型|占位符|转义符(代码片段)

...型数字字面量语法(Numberliteralssyntax)浮点型和复数布尔值字符串字符串转义符多行字符串字符串操作byte和rune类型修改字符串类型转换%占位符一般占位符布尔占位符整数占位符浮点数和复数占位符 查看详情

如何使用格式化占位符本地化字符串?

】如何使用格式化占位符本地化字符串?【英文标题】:HowdoIlocalizeastringwithformattingplaceholders?【发布时间】:2011-02-0300:45:10【问题描述】:如何使用NSLocalizedString本地化包含占位符的字符串?例如:[NSStringstringWithFormat:@"Youcanafford... 查看详情

格式话输出

...-----------‘‘‘%(name,name,age,job,hobbie)#这?的%号就是把前?的字符串与括号后?的变量关联起来print(info) %s就是代表字符串占位符%d是数字占位符(必须是int类型)%f是浮点数占位符(%.2f,表示保留2位小数)在字符串中如果使?了%s... 查看详情

java中有啥方法可以读取占位符的字符串,并且把占位符替换成参数

我现在是从资源文件中读取一个字符串,这个字符串里面有占位符,读取结果如:xxxx0xxx1。现在要用一个方法把参数带入0和1中,java中好像有内置的方法,请问是什么,如果没有,求帮忙来个封装的类。谢谢直接调用MessageFormat.f... 查看详情

apache commons 日志记录是不是支持占位符?

】apachecommons日志记录是不是支持占位符?【英文标题】:Doesapachecommonsloggingsupportsplaceholders?apachecommons日志记录是否支持占位符?【发布时间】:2017-04-1513:18:12【问题描述】:Here是关于apachecommonslogging的用户指南,但它没有关于... 查看详情