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

背景

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

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

工具

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 技术交流为主

备注:博客园

原文地址:https://www.cnblogs.com/shiyajian/p/10134420.html

时间: 2024-10-07 15:38:34

Java日志格式应该是占位符还是字符串拼接的相关文章

js使用占位符替换字符串

js使用占位符替换字符串是一个ES6中的模版字符串语法. 在``中使用 ${} var a = 5; var b = 10; console.log(`Fifteen is ${a + b} and not ${2 * a + b}.`); Fifteen is 15 and not 20.

完整修改删除,占位符防治字符串攻击

完整修改删除相对于修改删除就是在修改删除之前先进性判断是否有要进行操作的对象,如果有再进行修改或者删除.也就是在修改删除之前先进行查询. 以修改为例 static void Main(string[] args) { bool has = false;//定义一个变量判断是否有该对象 Console.Write("请输入要修改的用户名:"); string Uname = Console.ReadLine(); SqlConnection conn = new SqlConnectio

Java日志框架SLF4J和log4j以及logback的联系和区别

1.SLF4J(Simple logging Facade for Java) 意思为简单日志门面,它是把不同的日志系统的实现进行了具体的抽象化,只提供了统一的日志使用接口,使用时只需要按照其提供的接口方法进行调用即可,由于它只是一个接口,并不是一个具体的可以直接单独使用的日志框架,所以最终日志的格式.记录级别.输出方式等都要通过接口绑定的具体的日志系统来实现,这些具体的日志系统就有log4j,logback,java.util.logging等,它们才实现了具体的日志系统的功能. 如何使用SL

Spring_属性占位符

忍耐和坚持虽是痛苦的事情,但却能渐渐地为你带来好处.--奥维德 属性占位符 Spring一直支持将属性定义到外部的属性的文件中,并使用占位符值将其插入到Spring bean中. 占位符的形式为使用"${}"包装的属性名称,为了使用属性占位符,我们必须配置一个PropertyPlaceholderConfigurer或PropertySourcesPlaceholderConfigurer实例,从Spring 3.0开始,推荐使用PropertySourcesPlaceholderCo

Android之使用JAVA占位符格式数据(很实用)

小编虽然是学java出生,但工作之后就一直从事android开发,很多java基础都忘记完了,最近一年从ES换到了AS,原来的很多习惯都收到了挑战,比如我喜欢ES写方法的时候先在JAVA project中写个main方法验证下对不对,比如数据拆分,时间对比等等,但AS使用中,因为和ES很多环境变量冲突,就把ES卸载了,现在很多都不方便. 在开发中使用比较多的就是设置view的值/给view填充值得时候,需要格式化数据,小编今天用了一写时间,做了下小小的整理 1.%s 字符串类型 用处:多用于字符

Java 占位符使用 和 修饰符

Java中占位符的使用 String类的format()方法 String类的format()方法用于创建格式化的字符串以及连接多个字符串对象.熟悉C语言的同学应该记得C语言的sprintf()方法,两者有类似之处.format()方法有两种重载形式. format(String format, Object... args) 新字符串使用本地语言环境,制定字符串格式和参数生成格式化的新字符串. format(Locale locale, String format, Object... arg

Java C# C语言中的占位符

一般拼接一段字符串在编程中是很常见的事,下面简单做个总结: 什么是占位符?占位符就是先占住一个固定的位置,等着你再往里面添加内容的符号. 1.Java中处理方法: package com.amos; import java.text.MessageFormat; /** * Created by amosli on 14-7-24. */ public class Test { public static void main(String args[]) { //拼接一段string 常用的方法

C语言中的格式占位符

C语言中的格式占位符: %a,%A 读入一个浮点值(仅C99有效) %c 读入一个字符 %d 读入十进制整数 %i 读入十进制,八进制,十六进制整数 %o 读入八进制整数 %x,%X 读入十六进制整数 %s 读入一个字符串,遇空格.制表符或换行符结束. %f,%F,%e,%E,%g,%G 用来输入实数,可以用小数形式或指数形式输入. %p 读入一个指针 %u 读入一个无符号十进制整数 %n 至此已读入值的等价字符数 %[] 扫描字符集合 %% 读%符号

Java字符串占位符

一,问题描述 在C#中,替换字符串中占位符可以使用如下: string domain = "www.oschina.net";              Console.WriteLine(String.Format("该域名{0}被访问了N次.", domain));          那么在Java中如何实现这类情景下的替换工作呢????     二,解决方案         Java里面的文本替换有多种方式,我例举两种,仅仅做个笔记             1