Inefficient use of string concatenation

2019-01-25 09:55发布

I was creating a logger in my java-app (with NetBeans as IDE) when suddenly I saw a warning saying: "Inefficient use of string concatenation in logger".

My oringinal code is

srcLogger.getLogger().log(Level.INFO,"UploadBean.doUpload completado [" + file.getName() + "]\n");

but NetBeans suggested to convert it to a template (what a "template" means here?) giving this code:

srcLogger.getLogger().log(Level.INFO, "UploadBean.doUpload completado [{0}]\n", file.getName());

What's the different between these two ways of concatenation, I never used the latter though.

Cheers.

6条回答
聊天终结者
2楼-- · 2019-01-25 10:34

The warning that you get from NetBeans is giving you the shortest justification for avoiding concatenation in the log statement.

  1. Log messages that are not going to get sent to the log are not constructed when you use the template style. You can even optimize the style a bit more by avoiding method calls in the list of arguments.

But there are some other reasons to choose to use the template style for log message.

a. Avoids possible overhead of concat. As others have pointed out, this is not a huge issue with recent javac's.

b. Your code is better prepared for internationalization/localization. While you may think... this code will never need that level of concern... it is surprising how far code goes after it is initially written.

查看更多
相关推荐>>
3楼-- · 2019-01-25 10:50

The real win here is that you don't have to do any string handling at all (either concatenation or template expansion) if the logger is configured to not log at INFO level.

That is, the logger can decided to do nothing at all without having to go anywhere near any kind of string manipulation.

查看更多
smile是对你的礼貌
4楼-- · 2019-01-25 10:52

I'd ignore the warning (and switch if it off, if possible). The concatenation is not that inefficient, because modern compilers replace it with an efficient implementation based on StringBuilder (you'll see it if you look at the classfile's bytecode).

The suggested replacement doesn't concatenate Strings but it requires some extra processing to parse the template and merge it with the parameters.

Netbeans, that's a bad advice.

This is true for Java 1.5+. Older versions of Java (may) create a lot of unused String instances during concatenation..

查看更多
再贱就再见
5楼-- · 2019-01-25 10:54

The message is not referring to the cost of the String concatenation in of itself. The other answers are absolutely right when they say that a StringBuilder will be used.

The main reason to use a Message Template is because the processing is only done when the logging level is being displayed!

Let us use these two examples:

srcLogger.getLogger().log(Level.INFO,"UploadBean.doUpload completado [" + file.getName() + "]\n");
srcLogger.getLogger().log(Level.INFO, "UploadBean.doUpload completado [{0}]\n", file.getName());

With debug level INFO on: Both have to get the filename from File, both have to update the string, generate a new one, display it.

With debug level INFO off: The second answer passes through the name of the File object (which is a simple query), the log() method checks the INFO level and returns immediately. No String processing is performed at all!

Now imagine that instead of a simple file.getName() we were logging a more complex object, one that itself needed a lot of string concatenation in the toString() method. By logging those objects directly none of that processing is done at all. toString() is never even called unless the debug level is being displayed.

So Message Template is not more efficient in the case where the logging is being displayed, but it is enormously more efficient (particularly in cases of non-trivial logging) when the logging is not being displayed. One of the goals of logging should be that if the logging is turned off it has the smallest possible impact on the performance of the system.

查看更多
做自己的国王
6楼-- · 2019-01-25 10:54

Since strings are immutable in Java, when you concatenate String objects you actually create an entirely new object. Using something like the template Netbeans suggests or StringBuilder prevents you from having to create all of those intermediate objects, which take time and resources.

查看更多
对你真心纯属浪费
7楼-- · 2019-01-25 10:58

A template means exactly that, it's supposed a template for a String, rather than a String itself. The idea is that the {0} bit will be replaced with the first argument which appears after it in the list (file.getName()). This follows the pattern of String's format method.

I've not seen any performance tests to verify whether or not this is quicker or not. As other answers have pointed out leaving it as is won't be particularly slow as a StringBuilder will be used in place of a regular String by the compiler. However, as @dty points out, I think it should be quicker in the case that the logging level is set so that statement isn't actually logged, since there is no work required to construct the string to output. Also, since the entire template string is a single literal, this will be added to the String pool by the compiler. This means that all instances of this particular String will be pointing to the same actual instance - so if the statement is not actually logged then it doesn't even have to allocate memory to store this string, it just looks it up, which should be more efficient.

查看更多
登录 后发表回答