-
Notifications
You must be signed in to change notification settings - Fork 24.9k
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Replace StringBuffer with StringBuilder where possible #30964
Conversation
StringBuilder should be used in preference to StringBuffer as it is fully compatible but faster, as it performs no synchronization. In the changed locations the buffer is only used in local scope, so should not need synchronization.
Pinging @elastic/es-core-infra |
I don't expect this to be much of an improvement in most places, but I was just reminded about the differences by somthing I read and found it interesting to see where we use it in out codebase and can potentially change it. |
@@ -474,7 +474,7 @@ public static String replaceFirst(CharSequence receiver, Pattern pattern, Functi | |||
// CharSequqence's toString is *supposed* to always return the characters in the sequence as a String | |||
return receiver.toString(); | |||
} | |||
StringBuffer result = new StringBuffer(initialBufferForReplaceWith(receiver)); | |||
StringBuilder result = new StringBuilder(initialBufferForReplaceWith(receiver)); | |||
m.appendReplacement(result, Matcher.quoteReplacement(replacementBuilder.apply(m))); |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
This method was added in Java 9 so I don't think we can use it here until Java 8 isn't a thing for master.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
For what it is worth when I wrote this the first time around I didn't see any real performance penalty for using StringBuffer. I believe the JVM can remove the uncontended synchronization fairly effectively in this case.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Makes sense, didn't know about the method. And yes, I don't see any real issue here as well, might as well keep it.
Maybe we should consider making it and Vector forbidden APIs to prevent them from re-appearing in the future. |
@jpountz there are legitimate usages, e.g. when having to use third party APIs that require it (e.g. Joda does in some places), so I wouldn't block it per se. |
I was thinking we could tag all methods that actually need it with |
@@ -101,7 +101,7 @@ public Object getValue(String key) throws IOException { | |||
* String*Buffer* because that is what the Matcher API takes. In modern versions of java the uncontended synchronization is very, |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
This comment looks obsolete
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Yeah, I should read more comments to save me some trouble ;-) Nik is right here of course.
I want to point out that this has been suggested before (this is not an argument against). For a locally allocated |
Here are my previous comments on making |
@@ -65,7 +65,7 @@ | |||
|
|||
private static String toCamelCase(String s) { | |||
Matcher m = UNDERSCORE_THEN_ANYTHING.matcher(s); | |||
StringBuffer sb = new StringBuffer(); | |||
StringBuilder sb = new StringBuilder(); | |||
while (m.find()) { | |||
m.appendReplacement(sb, m.group(1).toUpperCase()); |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
This one has the same problem with java 8.
@@ -101,7 +101,7 @@ public Object getValue(String key) throws IOException { | |||
* String*Buffer* because that is what the Matcher API takes. In modern versions of java the uncontended synchronization is very, | |||
* very cheap so that should not be a problem. | |||
*/ | |||
StringBuffer result = new StringBuffer(key.length()); | |||
StringBuilder result = new StringBuilder(key.length()); |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
This one also has the same problem with java 8.
@@ -191,7 +191,7 @@ private Object getValue(List<Object> path, String key) throws IOException { | |||
} | |||
} | |||
String builtPath = Matcher.quoteReplacement(pathBuilder.toString()); | |||
StringBuffer newKey = new StringBuffer(key.length()); | |||
StringBuilder newKey = new StringBuilder(key.length()); |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
This one also uses a Java 9 method.
To be clear, I don't worry about performance at all, only consistency. |
@jasontedor thanks for the comment, I didn't know this already had a backstory. I just opened this mostly as an exercise while I was reading the code. I'm happy to not do this change since its nowhere near any performance-critical location. |
The java compatibility issues leave little to change in this PR. |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I think it'd be fine to merge it.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I left a comment about ActiveDirectorySIDUtil
.
@@ -38,7 +38,7 @@ static String convertToString( byte[] bytes ) | |||
} | |||
|
|||
char[] hex = Hex.encodeHex( bytes ); | |||
StringBuffer sb = new StringBuffer(); | |||
StringBuilder sb = new StringBuilder(); |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I think that we should avoid changing this source file. It is from upstream (see #30972 to fix the license) and we should not deviate unless absolutely necessary (it could get reverted in a future import from upstream anyway).
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Makes sense, will close this then.
StringBuilder can be used in preference to StringBuffer as it is fully
compatible but faster, since it performs no synchronization.
In the changed locations, the buffer is only accessed in local scope, so
no synchronization should be needed.