Repository: groovy Updated Branches: refs/heads/master d1308e20b -> 9d94e2e4f
GROOVY-7873 - Regression performance issue in string methods (closes #356) In order to implement CharSequence the GString implementation must call toString each time a CharSequence method is invoked. This is expensive, so GStrings should be converted toString if methods such as charAt are going to be called from a loop. Project: http://git-wip-us.apache.org/repos/asf/groovy/repo Commit: http://git-wip-us.apache.org/repos/asf/groovy/commit/9d94e2e4 Tree: http://git-wip-us.apache.org/repos/asf/groovy/tree/9d94e2e4 Diff: http://git-wip-us.apache.org/repos/asf/groovy/diff/9d94e2e4 Branch: refs/heads/master Commit: 9d94e2e4f5b8ec84296ac3d92851807df933b2d7 Parents: d1308e2 Author: John Wagenleitner <jwagenleit...@apache.org> Authored: Fri Jun 24 22:21:06 2016 -0700 Committer: John Wagenleitner <jwagenleit...@apache.org> Committed: Fri Jun 24 22:22:12 2016 -0700 ---------------------------------------------------------------------- .../org/codehaus/groovy/runtime/StringGroovyMethods.java | 11 ++++++++--- 1 file changed, 8 insertions(+), 3 deletions(-) ---------------------------------------------------------------------- http://git-wip-us.apache.org/repos/asf/groovy/blob/9d94e2e4/src/main/org/codehaus/groovy/runtime/StringGroovyMethods.java ---------------------------------------------------------------------- diff --git a/src/main/org/codehaus/groovy/runtime/StringGroovyMethods.java b/src/main/org/codehaus/groovy/runtime/StringGroovyMethods.java index 2c8f794..0817dd2 100644 --- a/src/main/org/codehaus/groovy/runtime/StringGroovyMethods.java +++ b/src/main/org/codehaus/groovy/runtime/StringGroovyMethods.java @@ -434,15 +434,18 @@ public class StringGroovyMethods extends DefaultGroovyMethodsSupport { int i = 0; + // GROOVY-7873: GString calls toString() on each invocation of CharSequence methods such + // as charAt which is very expensive for large GStrings. + CharSequence cs = (self instanceof GString) ? self.toString() : self; while (i < len) { - final char ch = self.charAt(i++); + final char ch = cs.charAt(i++); switch (ch) { case '\r': sb.append(lineSeparator); // Eat the following LF if any. - if ((i < len) && (self.charAt(i) == '\n')) { + if ((i < len) && (cs.charAt(i) == '\n')) { ++i; } @@ -601,7 +604,9 @@ public class StringGroovyMethods extends DefaultGroovyMethodsSupport { private final CharSequence delegate; public LineIterable(CharSequence cs) { - this.delegate = cs; + // GROOVY-7873: GString calls toString() on each invocation of CharSequence methods such + // as charAt which is very expensive for large GStrings. + this.delegate = (cs instanceof GString) ? cs.toString() : cs; } @Override