[
https://issues.apache.org/jira/browse/GROOVY-6360?page=com.atlassian.jira.plugin.system.issuetabpanels:comment-tabpanel&focusedCommentId=17285053#comment-17285053
]
Daniel Sun commented on GROOVY-6360:
------------------------------------
[~vy]
Even if using Groovy 4 with GROOVY-9637 fixed, we have to use
{{@KnownImmutable}} to mark customed classes to tell Groovy that their instance
is immutable, then their string literal will be cached by {{GString}} instance.
*Using KnownImmutable*
{code:java}
final class Test {
@groovy.transform.KnownImmutable
private static final class Item {
private int toStringInvocationCount = 0
@Override
synchronized String toString() {
toStringInvocationCount++
return "item"
}
}
static void main(String[] args) {
Item item = new Item()
new StringBuilder().append("item: ${item}")
System.out.println(item.toStringInvocationCount) // yield 1
}
}
{code}
*Not using KnownImmutable*
{code:java}
final class Test {
//@groovy.transform.KnownImmutable
private static final class Item {
private int toStringInvocationCount = 0
@Override
synchronized String toString() {
toStringInvocationCount++
return "item"
}
}
static void main(String[] args) {
Item item = new Item()
new StringBuilder().append("item: ${item}")
System.out.println(item.toStringInvocationCount) // yield 12
}
}
{code}
P.S. It would be interesting to investigate why {{toString}} is called 12 times
;-)
> GString performance is slow with String's method
> ------------------------------------------------
>
> Key: GROOVY-6360
> URL: https://issues.apache.org/jira/browse/GROOVY-6360
> Project: Groovy
> Issue Type: Improvement
> Components: groovy-jdk
> Affects Versions: 2.1.7
> Reporter: Linh Pham
> Assignee: Paul King
> Priority: Minor
> Fix For: 3.0.8, 4.0.0-alpha-3
>
> Time Spent: 1h 50m
> Remaining Estimate: 0h
>
> GString implementation of String's method is very expensive. With trim(), it
> can be 10 times slower than String's counterpart.
> *Steps to reproduce:*
> A small test program showed GString.trim() is 10 times slower than
> String.trim().
> {code}
> def a = " content "
> def b = " ${'content'} "
> println "a class: ${a.class}" //output: class java.lang.String
> println "b class: ${b.class}" //output: class
> org.codehaus.groovy.runtime.GStringImpl
> long start = System.currentTimeMillis()
> 10000000.times {
> a.trim()
> }
> println "String trim completed in ${System.currentTimeMillis() - start} ms."
> //output *909* ms
> start = System.currentTimeMillis()
> 10000000.times {
> b.trim()
> }
> println "GString trim completed in ${System.currentTimeMillis() - start} ms."
> //output: *9321 *ms
> {code}
> We can get around the problem by calling toString() on GString before
> invoking methods, BUT it should be supported inside the Groovy runtime.
> More info at this thread: http://markmail.org/thread/4cti6dgb7pmrzqbl
--
This message was sent by Atlassian Jira
(v8.3.4#803005)