Yeah, doesn't exactly seem ideal. But at the end of the day, we're
not exactly looking for RecordMapper caching, but instead caching of
reflection information. Would it be possible to change the annotation
utils methods, such as getAnnotatedMembers(), to accept a
Configuration object as an argument, then do something like the
following:
static final List<java.lang.reflect.Field>
getAnnotatedMembers(Configuration configuration, Class<?> type, String
name) {
if ( configuration instanceof SomeMagicalInterface ) {
((SomeMagicalInterface)configuration).getCachedStuff(type, name);
}
...
}
If we are focusing on just providing caching for reflection, it may
make sense to not specifically tie the interface and logic to the
record mapper. In fact you could just use Configuration.data(...) as
your cache.
Darren
On Fri, Jan 24, 2014 at 7:43 AM, Lukas Eder <[email protected]> wrote:
> Hi Darren,
>
> I'm looking at caching in DefaultRecordMapperProvider. A canonical solution
> would be this one here:
>
> public class DefaultRecordMapperProvider implements RecordMapperProvider {
>
> private final ConcurrentHashMap<Key<?, ?>, DefaultRecordMapper<?, ?>>
> cache = new ConcurrentHashMap<Key<?, ?>, DefaultRecordMapper<?, ?>>();
>
> @SuppressWarnings("unchecked")
> @Override
> public final <R extends Record, E> RecordMapper<R, E>
> provide(RecordType<R> rowType, Class<? extends E> type) {
> Key<R, E> key = new Key<R, E>(rowType, type);
> DefaultRecordMapper<?, ?> mapper = cache.get(key);
>
> if (mapper == null) {
> mapper = new DefaultRecordMapper<R, E>(rowType, type);
> cache.put(key, mapper);
> }
>
> return (RecordMapper<R, E>) mapper;
> }
>
> private static class Key<R extends Record, E> {
> final RecordType<R> rowType;
> final Class<? extends E> type;
>
> Key(RecordType<R> rowType, Class<? extends E> type) {
> this.rowType = rowType;
> this.type = type;
> }
>
> @Override
> public int hashCode() {
> final int prime = 31;
> int result = 1;
> result = prime * result + ((rowType == null) ? 0 :
> rowType.hashCode());
> result = prime * result + ((type == null) ? 0 :
> type.hashCode());
> return result;
> }
>
> @Override
> public boolean equals(Object that) {
> if (this == that) return true;
> if (that == null) return false;
>
> Key<?, ?> other = (Key<?, ?>) that;
> if (rowType == null) {
> if (other.rowType != null)
> return false;
> }
> else if (!rowType.equals(other.rowType))
> return false;
> if (type == null) {
> if (other.type != null)
> return false;
> }
> else if (!type.equals(other.type))
> return false;
> return true;
> }
> }
> }
>
> It is evident that the cache object might explode as it depends on the {
> RecordType × Class<?> } cartesian product, where RecordType itself has an
> immense "possible instances" complexity of O(n!) (all the permutations of
> possible field combinations). A possibility would be to use a LRUCache, but
> that might not be generally applicable.
>
> What is your opinion on this? Or anyone else on the group?
>
> Lukas
>
>
> 2014/1/20 Lukas Eder <[email protected]>
>>
>> Hi Darren,
>>
>> 2014/1/17 Darren Shepherd <[email protected]>
>>>
>>> Now that I think about it if the caching was done in the Configuration
>>> object, not stored in some global static, then that would seem like an
>>> acceptable solution. I can't image that in a dynamic classloader situation
>>> that you would be sharing the Configuration object such that it would cause
>>> a memory. Or at least in that situation you give the option to disable it.
>>
>>
>> Hmm, nice thinking. In principle, the Configuration object already holds a
>> reference to a DefaultRecordMapperProvider. It would probably be safe to
>> implement caching of { Class, DefaultRecordMapper } pairs in there and
>> enable it by default. DefaultRecordMapperProvider could then have a couple
>> of overridable properties that allow for influencing caching, e.g. to turn
>> it off, or to invalidate it. I have registered #2965 for this:
>> https://github.com/jOOQ/jOOQ/issues/2965
>>
>> This can be implemented for jOOQ 3.3 and jOOQ 3.2.3
>>
>> I guess that the last time this issue was discussed, there hadn't been
>> such an elegant SPI yet to inject record mapping behaviour.
>>
>>>
>>> I found an IBM bug related to this, which is obviously for their J9 JVM,
>>> but it seems to indicate that java 7 introduced this slow down.
>>> http://www-01.ibm.com/support/docview.wss?uid=swg1IV53758
>>
>>
>> Interesting find!
>>
>> Cheers
>> Lukas
>
>
> --
> You received this message because you are subscribed to a topic in the
> Google Groups "jOOQ User Group" group.
> To unsubscribe from this topic, visit
> https://groups.google.com/d/topic/jooq-user/YpIpRVVsd5A/unsubscribe.
> To unsubscribe from this group and all its topics, send an email to
> [email protected].
> For more options, visit https://groups.google.com/groups/opt_out.
--
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/groups/opt_out.