Skip to content
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

Closed
wants to merge 3 commits into from

Conversation

cbuescher
Copy link
Member

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.

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.
@cbuescher cbuescher added >non-issue review :Core/Infra/Core Core issues without another label v7.0.0 labels May 30, 2018
@elasticmachine
Copy link
Collaborator

Pinging @elastic/es-core-infra

@cbuescher
Copy link
Member Author

cbuescher commented May 30, 2018

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)));
Copy link
Member

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.

Copy link
Member

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.

Copy link
Member Author

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.

@jpountz
Copy link
Contributor

jpountz commented May 30, 2018

Maybe we should consider making it and Vector forbidden APIs to prevent them from re-appearing in the future.

@cbuescher
Copy link
Member Author

@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.

@jpountz
Copy link
Contributor

jpountz commented May 30, 2018

I was thinking we could tag all methods that actually need it with @SuppressForbidden to make sure we only use those classes when there is no other choice.

@@ -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,
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This comment looks obsolete

Copy link
Member Author

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.

@jasontedor
Copy link
Member

I want to point out that this has been suggested before (this is not an argument against). For a locally allocated StringBuffer, the JVM will optimize away the locks because it knows through escape analysis that they are not needed. Therefore, we expect no improvement from this change in the case of locally allocated StringBuffers that never escape.

@jasontedor
Copy link
Member

Here are my previous comments on making StringBuffer forbidden; I still think that we should not do this.

@@ -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());
Copy link
Member

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());
Copy link
Member

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());
Copy link
Member

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.

@jpountz
Copy link
Contributor

jpountz commented May 30, 2018

To be clear, I don't worry about performance at all, only consistency.

@cbuescher
Copy link
Member Author

@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.

@cbuescher
Copy link
Member Author

The java compatibility issues leave little to change in this PR.
I'm happy to close this as well, now that it's really more Much ado bout nothing. Sorry for the noise.

Copy link
Member

@nik9000 nik9000 left a 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.

Copy link
Member

@jasontedor jasontedor left a 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();
Copy link
Member

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).

Copy link
Member Author

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.

@cbuescher cbuescher closed this May 30, 2018
@cbuescher cbuescher deleted the replace-StringBuffers branch May 30, 2018 19:08
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
:Core/Infra/Core Core issues without another label >non-issue v7.0.0-beta1
Projects
None yet
Development

Successfully merging this pull request may close these issues.

7 participants