I have responded to this message on your "repost".

Cheers
Lukas

2012/11/4 Adam <[email protected]>:
> Hi Lucas,
>
> I have been watching your project for a while now and have to say that you
> are dying a fantastic job!
> (...have you got a full time job as well?)
>
> Couple of months back I decided to use jOOQ (for all the obvious reasons) in
> my project. I am now at the
> point when I have got a decent piece of functionality implemented and
> started to write some high level tests
> for my use case. Each tests runs with a simple DYI (do it yourself) profiler
> that gives me time breakdown
> for the relevant methods within the execution stack.
>
> During these tests I have first noticed that it takes disproportionally long
> time to construct the Factory class.
> To give you an example I have a test case that inserts 12 records for 7
> different entity types (in other words
> 12 records into 7 tables). The whole test runs 266 ms and out of this 140 ms
> is spent to construct the Factory
> (with a JDBC connection and H2 Dialect in my case). After checking the
> source code I did not find anything there
> that should take so long so I added a couple of traces there and run it
> through the debugger. I have  noticed
> that after the initial Factory constructor call there are additional 15
> calls as well. These calls come from
> the default static initialiser that is run for each database dialect.
>
>     static {
>         for (SQLDialect dialect : SQLDialect.values()) {
>             Factory.DEFAULT_INSTANCES[dialect.ordinal()] = new
> Factory(dialect);
>         }
>     }
>
> All in all one could say that this is not a big deal as you construct the
> factory once (and incur this cost
> only once) but since the Factory is constructed with the requested dialect
> it seems a bit pointless to have this
> done for all available dialects.
>
>
> The side effect/product of the added traces in the Factory constructor
> brought up another issue. The Factory
> constructor is called multiple times after the initial instance of the
> Factory is created. In this specific test case
> there are additional 110 calls. The story starts with the construction of
> the insert statement - in my case one
> of them looks like this:
>
>         return ftry
>             .insertInto(CATEGORY,
>                         CATEGORY.ID,
>                         CATEGORY.USR,
>                         CATEGORY.VER,
>                         CATEGORY.TYPE,
>                         CATEGORY.NAME)
>             .values(ent.getId(),
>                       ent.getUser(),
>                     newVer,
>                     ent.getEnum(Property.CategoryType),
>                     ent.getString(Property.Name));
>
> Which eventually leads to adding key/value pairs to a linked hash map that
> calls hashCode() on TableFiedlImp class
> that is implemented in the AbstractQueryPart class:
>
>     @Override
>     public int hashCode() {
>         // This is a working default implementation. It should be overridden
> by
>         // concrete subclasses, to improve performance
>         return create().renderInlined(this).hashCode();
>     }
>
> Seems like something got forgotten here as this default implementation
> calls:
>
>     protected final Factory create() {
>         return create(getConfiguration());
>     }
>
> On the Factory class which then calls:
>
>     protected final Factory create(Configuration configuration) {
>         return Factory.getNewFactory(configuration);
>     }
>
> And then the constructor:
>
>     @SuppressWarnings("deprecation")
>     final static Factory getNewFactory(Configuration configuration) {
>         if (configuration == null) {
>             return
> getNewFactory(DefaultConfiguration.DEFAULT_CONFIGURATION);
>         }
>         else {
>             return new Factory(
>                 configuration.getDataSource(),
>                 configuration.getConnection(),
>                 configuration.getDialect(),
>                 configuration.getSettings(),
>                 configuration.getSchemaMapping(),
>                 configuration.getData());
>         }
>     }
>
>
>  The bottom line is that the constructor is called for each column of each
> record that is constructed.
>  (see the attached snapshot for the whole stack trace). I have not profiled
> any updates as yet but it
>  seems likely that the behaviour will be the same as they most likely reuse
> the same functionality.
>
>  Regards,
>  Adam
>
>  PS
>  It is a great shame that there is not a simple JUnit profiler add-on
> available which would show these
>  kinds of issue straight away - any takers?
>
>

Reply via email to