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 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.