伍佰目录 短网址
  当前位置:海洋目录网 » 站长资讯 » 站长资讯 » 文章详细 订阅RssFeed

日志输出都有歧义!字符拼接 VS 占位符,到底该采用哪种方式?

来源:本站原创 浏览:68次 时间:2022-11-19
前言

说来也巧,这几天正在看一本书,叫做《Java系统性能优化实战》,李家智著的,在代码审查这章中提到了一个关于日志输出问题,先看一下我们原本是怎么输出信息的,如下。

private static  Logger logger = LoggerFactory.getLogger(FileManageApplication.class);

 public static void main(String[] args) {
  logger.info("日志输出{}",1);
 }

第一个参数是格式化模板,“{}”是占位符,第二个参数是类型可以是Object... arguments的,会将第一个参数中的"{}"依次替换为这个数组中的数据,不出意外的话,会输出如下信息。

2021年01月07日 19:52:09:INFO main (FileManageApplication.java:35) - 日志输出1

但是他却不建议使用这种方式,理由是日志框架内部会有一个把占位符"{}"替换成目标变量的耗时过程,考虑到info方法可能被频繁调用,对性能有影响,所以建议直接拼接,代码如下:

public static void main(String[] args) {
 User user  =getUser();
 logger.info("用户名:"+user.getUserName());
}

这听起来似乎也有几分道理,但是在今天早上刷到了一篇公众号文章,里面也恰好提到了这个问题(是个某大V),里面这样说:“不要进行字符串拼接,那样会产生很多String对象,占用空间,影响性能”。

what???

并且他给出了一个反例,如下:

logger.debug("Processing trade with id: " + id + " symbol: " + symbol);

并且还有个正例,如下:

logger.debug("Processing trade with id:[{}] and symbol : [{}] ", id, symbol)

另外这样的格式,可读性更好,对于排查问题更有帮助。

所以,最后我们用什么方法?

下面我们还是自己看测试一下把。

时间比较使用拼接方式
public class Main {
    private static Logger logger = LoggerFactory.getLogger(Main.class);
    public static void main(String[] args) {
        long startTimer = System.currentTimeMillis();
        for (int i = 0; i < 200000; i++) {
            logger.info("i="+i);
        }
        System.out.println(System.currentTimeMillis()-startTimer);
        
    }
}

运行10次,结果是如下,平均是512.2。

534、510、486、518、495、505、526、507、511、530
使用模板方式
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

public class Main {
    private static Logger logger = LoggerFactory.getLogger(Main.class);
    public static void main(String[] args) {
        long startTimer = System.currentTimeMillis();
        for (int i = 0; i < 200000; i++) {
            logger.info("i={}",i);
        }
        System.out.println(System.currentTimeMillis()-startTimer);
    }
}

运行10次,结果是如下,平均是642.9。

654、648、599、624、678、660、643、656、583、684

确实如书中所说,替换"{}"的过程比较耗时。

这里没使用System.out.println()做比较,因为他实在太慢了,因为内部会涉及到加锁。

内存占用比较
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

import javax.swing.*;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;

public class Main extends JFrame {
    private static Logger logger = LoggerFactory.getLogger(Main.class);

    public Main() {
        this.setSize(300, 300);
        this.setVisible(true);
        this.setDefaultCloseOperation(EXIT_ON_CLOSE);

        JButton jButton = new JButton("开始");
        jButton.addActionListener(new ActionListener() {
            public void actionPerformed(ActionEvent e) {
                for (int i = 0; i < 1000000; i++) {
                    logger.info("i={}",i);
//                    logger.info("i="+ i);
                }
            }
        });
        this.add(jButton);
    }

    public static void main(String[] args) {
        new Main();
    }
}

模板方式

点击按钮等待输出完成后,内存停留在112,764KB。

执行GC后降到13,484KB。

拼接方式

点击按钮等待输出完成后,内存停留在128,014KB,相差15,250KB。

执行GC后降到17,777KB。

在这次比较中,拼接方式占用的内存较高,也符合公众号中所说。

结论

显然都各胜一筹,所以只能看看自己需求了,另外在如Tomcat源码中,使用的也是拼接方式....

还有在阿里巴巴Java开发手册中这样说....

- END -


  推荐站点

  • At-lib分类目录At-lib分类目录

    At-lib网站分类目录汇集全国所有高质量网站,是中国权威的中文网站分类目录,给站长提供免费网址目录提交收录和推荐最新最全的优秀网站大全是名站导航之家

    www.at-lib.cn
  • 中国链接目录中国链接目录

    中国链接目录简称链接目录,是收录优秀网站和淘宝网店的网站分类目录,为您提供优质的网址导航服务,也是网店进行收录推广,站长免费推广网站、加快百度收录、增加友情链接和网站外链的平台。

    www.cnlink.org
  • 35目录网35目录网

    35目录免费收录各类优秀网站,全力打造互动式网站目录,提供网站分类目录检索,关键字搜索功能。欢迎您向35目录推荐、提交优秀网站。

    www.35mulu.com
  • 就要爱网站目录就要爱网站目录

    就要爱网站目录,按主题和类别列出网站。所有提交的网站都经过人工审查,确保质量和无垃圾邮件的结果。

    www.912219.com
  • 伍佰目录伍佰目录

    伍佰网站目录免费收录各类优秀网站,全力打造互动式网站目录,提供网站分类目录检索,关键字搜索功能。欢迎您向伍佰目录推荐、提交优秀网站。

    www.wbwb.net