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.
The warning that you get from NetBeans is giving you the shortest justification for avoiding concatenation in the log statement.
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.
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.
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..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:
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 thetoString()
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.
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 orStringBuilder
prevents you from having to create all of those intermediate objects, which take time and resources.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 ofString
'sformat
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 particularString
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.