1. 程式人生 > >Java日誌格式應該是占位符還是字符串拼接

Java日誌格式應該是占位符還是字符串拼接

chap gen 詳細 測試結果 使用 自動展開 pre 自動 級別

背景

? 上次在群中,有個群友說自己把所有項目中,所有使用占位符打印日誌的方式都修改成為了字符串拼接的方式,因為他曾經看了一篇文章,說字符串拼接的形式比占位符形式的性能更好,這個話題引起了大家的廣泛討論。

? 在我印象中,我記得曾經看過的文章說,占位符的方式性能好,因為如果不打日誌的話,就不會進行字符串拼接,節省性能。最後抱著一探究竟的心態,我進行了一次日誌輸出方式的實驗。

工具

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 技術交流為主
備註:博客園

Java日誌格式應該是占位符還是字符串拼接