Hi Jochen,

@alas none of the constructors in the attachment is delegating using "this(..)". As a result I see a lot of  code duplication: From my Groovy code that is just a single ctor with default arguments, the code duplication is created by the Groovy compiler.

@How did you measure those timings?: In the real world scenario, the situation does not improve over time, i.e. the query SQL generation always takes the same time, no matter how many times the code is executed. Accordingly I collect the data using high performance timer around the ctor call in a test that does one SQL creation pass. (I have today written a test that only calls the ctor of multiple classes 50x in a row in a loop, but that paints the same picture...)

@I fail a bit to imagine that this is the fault of those table classes directly: Quite a few of them display the desired performance, but some are not, and the biggest offenders depend on the largest & deepest hierarchy of traits, some inheriting the same trait from more than one source - that is all the difference I can see (I tried to find other differences today, but the ones I saw, when checked, all had no impact on  performance).

@A trait X would produce also a class X.Trait.Helper: I just realized that the reason I did not find these class files is, that IntelliJ does not display; the only files accessible are uninteresting @Trait annotated interface classes.

Unfortunately I am running out of time, I have a few days to get the queries back to acceptable speed, so I will probably actually have to rip out the traits, add their members to each class by hand and replace them with interfaces...

Thanks, Cheers,
mg


On 08/05/2023 21:09, Jochen Theodorou wrote:
On 07.05.23 23:05, MG wrote:
H(a|e)llo Jochen,

thank you for your reply.

@POJO is a Groovy 4 only feature, so I spent several hours getting our
project to build under groovy-4.0.11, then started profiling with
different settings, with the following results:

 1. The good news is, that we might have pinpointed the or at least one
    of the major reasons for the 2-3x performance drop when switching
    our project from Groovy 3 -> 4:
     1. The TBKMS_Table ctor call takes about 2 to 4 times as long on
        average when using groovy-4.0.11 out-of-the-box (i.e. indy),
        compared to other Groovy varieties (see below).
     2. https://issues.apache.org/jira/browse/GROOVY-10307

Sigh... I wish I had the time to produce a deeply integrated Graal
version of Groovy. With Java blocking the fast paths from the early
times and MethodHandles seemingly to take a lot of init time the current
situation is really really annoying.

Which reminds me... how did you measure those timings? With warmup-phase
and long running test? A single run? Something else?

 2. The not-so-good thing is, that alas the performance of non-indy
    groovy-4.0.11 with @CompileStatic @POJO on all involved traits is
    still a little bit slower than groovy-3.0.14 (default, i.e. non-indy)...

still a little bit slower means what? Actually I fail a bit to imagine
that this is the fault of those table classes directly. You could try
making the table class pojo-static as well to avoid any direct meta
class creation... though the decompiled class you showed me does not
implement GroovyObject, which suggests  you do that already.

 3. I have attached the performance measurements for different Groovy
    versions / compiler settings
     1. Average performance for calling the TBKMS_Table ctor ranges from
         > 400ms for groovy-4.0.11 out-of-the-box to < 100ms for
        groovy-3.0.14
     2. The expected/required performance would be < 1ms

That is still a long way off

 4. I also attached the decompiled ctor for the TBKMS_Table class, one
    of the two Table classes that compete for the longest ctor execution
    time (both all-in-all depend on about the same number of traits).

The decompiled version may hide some things.


Anyway, if I have

class A {

  public A(a,b=0) {
    println "some more code here"
  }
}

then this compiles to:

class A {
  public A(a,b) {
    println "some more code here"
  }
  public A(a) {
    this(a,0)
  }
}

the second constructor is really really small and exists only to
delegate to the first one, that does all the work.

So if you have

Table(String name, String shortName, Table parentTable = null, boolean
isReference = false, Schema schema = null) {....

then I expect something similar. Alas none of the constructors in the
attachment is delegating using "this(..)". As a result I see a lot of
code duplication.

     1. Regarding the trait classes: At the location corresponding to
        the involved traits package path I could only see some very
        small, trivial interface class files in IntelliJ...

It is mostly the ctor of the table and the generated trait helper
classes I am after. A trait X would produce also a class X.Trait.Helper,
which contains the connectivity code.

But again if the table is pojo-static and the traits too, then only code
called from there or code calling that can cause the breakdown in speed
I think. There is a small chance the with invokedynamic realized casts
are to be blamed, for some slowdown, but we should be surpassing Groovy
3 in a nonstatic variant here a lot already normally.

bye Jochen

Reply via email to