[
https://issues.apache.org/jira/browse/GROOVY-9601?page=com.atlassian.jira.plugin.system.issuetabpanels:comment-tabpanel&focusedCommentId=17144875#comment-17144875
]
Jochen Theodorou commented on GROOVY-9601:
------------------------------------------
[~daniel_sun] I think you should not test this with GCL#parseClass if you want
to know if antlr4 or antlr2 are to blame. Instead I would suggest to use the
parser directly to create the initial AST, to avoid class transforms and
especially class resolution to influence the parsing result.
If I use
{code}
import groovy.transform.CompileStatic
import org.codehaus.groovy.control.CompilationUnit
import org.codehaus.groovy.control.Phases
def code = """
package lab
import groovy.transform.CompileStatic
@CompileStatic
class MyClass {
${x->
1000.times{i -> x << """
public void myMethod${i}() {
println('method ${i} invoked...')
}
"""}
}
}
"""
def cu = new CompilationUnit()
cu.addSource 'hello.groovy', code
def time0 = System.nanoTime()
cu.compile Phases.CONVERSION
def time1 = System.nanoTime()
println "time = ${(time1 - time0) / 1000000}ms"
{code}
With this my test program I get 157-200ms for 2.5.12. and 170-224ms for 3.0.4.
The tendency is to be 10% slower
If I change the phase to class generation I see for 2.5.12 573-656ms and for
3.0.4 721-816ms. Now I see a tendency of being 50% slower.
This tells me three things:
a) parsing takes only a fraction of the time of total compilation
b) parsing seems not to cause the 50% slow down
c) doing this from the console makes a big difference compared to when running
from the command line.
If I remove @CompileStatic in the code to be compiled, because it is code that
causes the compiler to be a lot slower I get of course lower times:
3.0.4: 476-580ms
2.5.12: 419-467ms
And even though I see here a slow down of 10-20%, it is still very far away
from the 50% before.
Ah yes... I did not use the cache threshold property in any of this. I tried it
out and I did not really see a difference. But as you can see I have a range of
190ms in my times. That is because I executed the code like 20 times or so, to
see how stable the results are. On my machine they are not very stable, so this
is more than just a one-time event up or down, that caused this. Anyway... I
tend to believe that the difference you did observe is because of the
instability of the result, rather than that there is a real difference for this
test here.
All in all my culprit is not ANTLR4, but @CompileStatic.
> Parsing text into a class became much slower under Groovy 3.x
> -------------------------------------------------------------
>
> Key: GROOVY-9601
> URL: https://issues.apache.org/jira/browse/GROOVY-9601
> Project: Groovy
> Issue Type: Bug
> Components: class generator
> Affects Versions: 3.0.4
> Environment: Openjdk 11
> Reporter: Fabian Depry
> Assignee: Daniel Sun
> Priority: Major
> Fix For: 4.0.0-alpha-1, 3.0.5
>
> Attachments: 50000.png, image-2020-06-25-17-42-31-315.png,
> no_tuning.png
>
>
> Our Java application needs to execute dynamically generated Groovy code and
> we use the GroovyClassLoader to create a class from that generated code.
> When we tried to upgrade to Groovy 3.x we noticed a huge bump in the time it
> takes to create those dynamic classes (it became 10 times slower for some of
> them).
> Here is a very simple example of how we use the class loader:
> {code:java}
> package lab;
> import groovy.lang.GroovyClassLoader;
> public class GroovySpeedLab {
> public static void main(String[] args) {
> StringBuilder buf = new StringBuilder();
> buf.append("package lab\r\n");
> buf.append("\r\n");
> buf.append("import groovy.transform.CompileStatic\r\n");
> buf.append("\r\n");
> buf.append("@CompileStatic\r\n");
> buf.append("class MyClass {\r\n");
> for (int i = 0; i < 1000; i++) {
> buf.append("\r\n");
> buf.append(" public void myMethod").append(i).append("()
> {\r\n");
> buf.append(" println('method ").append(i).append("
> invoked...')\r\n");
> buf.append(" }\r\n");
> }
> buf.append("}\r\n");
> long start = System.currentTimeMillis();
> new GroovyClassLoader().parseClass(buf.toString());
> System.out.println("Done parsing in " + (System.currentTimeMillis() -
> start) + "ms");
> }
> }
> {code}
> While this runs very quickly (because the methods are trivial), it it still
> consistently 50% slower with 3.x (but I am including this example mainly to
> show our use-case, not to focus on its speed difference).
> Our real application has much more complex classes (and many of them) and its
> initialization went from a couple of minutes to 10+ minutes.
> Is there another way to parse a given Groovy class without taking such a big
> performance hit with the new version of Groovy?
> Note that we also use many small Script objects created by calling
> GroovyShell.parse() and we noticed the same performance hit for those (I
> assume it uses the same mechanism under the hood).
>
>
>
--
This message was sent by Atlassian Jira
(v8.3.4#803005)