Yes, the org.jooq.SchemaMapping reference is shared by any DSLContext that
uses the same Configuration.

I'd first like to see the actual benchmark that leads to contention before
we fix this. Perhaps I'm still missing something. My own (single-threaded,
so far) benchmarks show that *some* time is spent in the actual
map.contains() and map.get() methods, and that time can certainly be
optimised when users do not specify any mapping at all. But the
synchronized blocks are guarded by double-checked locking, so apart from
the application bootstrapping phase, I suspect that you shouldn't enter
those blocks too often in production.

Obviuously, benchmarks tend to be strongly biased towards being in a
bootstrapping phase. It's hard to avoid that effect.

I prefer not to use ConcurrentMaps whenever I can. The long-term overhead
such maps impose on read operations is far more significant than the bit of
time saved while bootstrapping essentially read-only data (caches).

2015-01-14 19:38 GMT+01:00 Robert DiFalco <[email protected]>:

> Very cool, I will check out these issues.
>
> I had a question about SchemaMapping. I noticed some "synchronized" blocks
> in there. But I could not figure out how these are used in a contended
> manner. Will these be shared by any DSLContext that shares the same
> Configuration?
>
> It seems like you could make this non-blocking by using
> ConcurrentMap#computeIfAbsent. If you can't use Java 8 you can just use
> #get and #putIfAbsent.
>
> Since it's rarely contested for a single mapping entry this would really
> move things along when many queries need to access this structure at once
> on different tables. Right now, even though they map different stuff, they
> all back up on the entire map. There is an edge condition where you will
> needlessly create a duplicate map, but this is an edge case that is far
> outweighed by not requiring every thread wait on the entire map.
>
>
> On Wednesday, January 14, 2015 at 8:25:00 AM UTC-8, Lukas Eder wrote:
>>
>> Hello,
>>
>> I did a bit of profiling myself, and I've found a couple of hotspots,
>> which I'm summarising here:
>> https://github.com/jOOQ/jOOQ/issues/3065
>>
>> There are a couple of places where excessive memory is consumed by not
>> reusing references to certain objects. For example:
>>
>> Avoid wrapping Field[] in a new RowImpl every time a Record is created
>> - https://github.com/jOOQ/jOOQ/issues/3954
>>
>> Avoid creating unnecessary Iterators and ArrayLists in
>> AbstractStore.getAttachables()
>> - https://github.com/jOOQ/jOOQ/issues/3947
>>
>> Replace ArrayList<ExecuteListener> by ExecuteListener[] in
>> ExecuteListeners to avoid excessive Iterator creation
>> - https://github.com/jOOQ/jOOQ/issues/3946
>>
>> AbstractScope creates an excessive amount of HashMaps, internally
>> - https://github.com/jOOQ/jOOQ/issues/3944
>>
>>
>>
>> Other hotspots include unnecessary processing, such as:
>>
>> Add RenderKeywordStyle.AS_IS
>> - https://github.com/jOOQ/jOOQ/issues/3931
>>
>>
>> There are more hotspots, which I'll resolve as we go.
>>
>> I believe that outside of a benchmark, the overhead is probably
>> negligible, but I can certainly see that there is an overhead to be noticed
>> in a benchmark. The largest overhead in memory consumption is caused by the
>> fact that all values are wrapped in boxed types, e.g. java.lang.Integer.
>> This will inevitably put some pressure on the GC.
>>
>> The largest overhead in CPU usage is caused by various occasions of
>> accessing Context.data(), a HashMap that is used while rendering SQL, for
>> the different QueryParts to communicate with each other. These features are
>> needed for emulation of complex SQL clauses. There is certainly room for
>> optimisation there as well, but the improvement will not be easy. I'll keep
>> looking for potential improvements.
>>
>> Also, there is some risk of contention in SchemaMapping, which
>> lazy-initialises its own data. As few users default to actually using the
>> SchemaMapping, I'm sure there is potential for bypassing that feature when
>> it is not active.
>>
>>
>> I'll keep you posted on this thread as soon as I discover anything else.
>>
>> Cheers
>> Lukas
>>
>> 2015-01-10 12:33 GMT+01:00 Lukas Eder <[email protected]>:
>>
>>> Hi Robert,
>>>
>>> Mere numbers don't really help assessing where time is lost. While I
>>> trust you have set up your benchmarks as well as possible, there might be a
>>> lot of hidden caveats that lead to significant overheads that would not
>>> appear in production, normally. Things like:
>>>
>>> - Debug logging being turned on
>>> - Tests not being bootstrapped (jOOQ needs to load all schema metadata,
>>> and caches a lot of stuff, just like JPA, of course)
>>>
>>> Ideally, for us to help you and verify your results, it would be great
>>> if you could publish your complete benchmarks in a completely reproducible
>>> way, e.g. on GitHub.
>>>
>>> I'm aware you private-messaged me parts of your benchmark code, but for
>>> the sake of traceability of this discussion, also in the future by other
>>> readers, it would be best if all relevant information would be contained
>>> and available from this Google Groups discussion.
>>>
>>> Cheers,
>>> Lukas
>>>
>>> 2015-01-09 18:01 GMT+01:00 Robert DiFalco <[email protected]>:
>>>
>>>> As you suspected, there was something wrong with my timing code. Here's
>>>> a more formal comparison for a query returning a single record. It is much
>>>> better. I'm not surprised that JPA is faster given that it is using a
>>>> pre-parsed query with @NamedQuery. I'm getting some weird overhead with
>>>> @Transactional and JOOQ that I need to figure out. For what it's worth,
>>>> when the number of records returned is around 250 the difference between
>>>> the two disappears.
>>>>
>>>> JOOQ-NP means no-parse, just sending a query string and processing
>>>> Results. JOOQ-RS does a parse like JOOQ but processes a ResultSet directly
>>>> instead of a JOOQ Result object.
>>>>
>>>> JPA     (avg=755.4us, total=3.776s, samples=4998, ops=1323.97)
>>>> JOOQ    (avg=824.4us, total=4.121s, samples=4998, ops=1213.11)
>>>> JOOQ-NP (avg=790.1us, total=3.949s, samples=4998, ops=1265.64)
>>>> JOOQ-RS (avg=821.9us, total=4.108s, samples=4998, ops=1216.65)
>>>> -- JPA     is 9.14% faster than JOOQ
>>>> -- JOOQ-NP is 4.33% faster than JOOQ
>>>> -- JOOQ-RS is 0.29% faster than JOOQ
>>>>
>>>>
>>>>
>>>> On Thursday, January 8, 2015 at 11:15:13 PM UTC-8, Lukas Eder wrote:
>>>>
>>>>>
>>>>>
>>>>> 2015-01-09 1:03 GMT+01:00 Robert DiFalco <[email protected]>:
>>>>>
>>>>>> I just did a little performance testing.
>>>>>>
>>>>>> FWIW, using Record is about 100ms per query slower than ResultSet.
>>>>>>
>>>>>> But worse yet using DSLContext is about 250ms slower than raw
>>>>>> Connection for a simple joined query. For Hibernate/JPA, using a
>>>>>> NamedNativeQuery is about the same time as using a raw JDBC connection 
>>>>>> and
>>>>>> about 300ms faster than JOOQ.
>>>>>>
>>>>>
>>>>> For a single query? That would be extremely surprising, or perhaps,
>>>>> specific to a particular API usage that might be out of the ordinary. It
>>>>> would be interesting to see this in action with a sample project...
>>>>>
>>>>  --
>>>> You received this message because you are subscribed to the Google
>>>> Groups "jOOQ User Group" group.
>>>> To unsubscribe from this group and stop receiving emails from it, send
>>>> an email to [email protected].
>>>> For more options, visit https://groups.google.com/d/optout.
>>>>
>>>
>>>
>>  --
> You received this message because you are subscribed to the Google Groups
> "jOOQ User Group" group.
> To unsubscribe from this group and stop receiving emails from it, send an
> email to [email protected].
> For more options, visit https://groups.google.com/d/optout.
>

-- 
You received this message because you are subscribed to the Google Groups "jOOQ 
User Group" group.
To unsubscribe from this group and stop receiving emails from it, send an email 
to [email protected].
For more options, visit https://groups.google.com/d/optout.

Reply via email to