Skip to content

Commit

Permalink
Use Guava's cache for method caching in InvocationHandlers since it's…
Browse files Browse the repository at this point in the history
… faster than Class#getMethod #90
  • Loading branch information
mp911de committed Jun 27, 2015
1 parent bfe05b9 commit c5f48c2
Show file tree
Hide file tree
Showing 3 changed files with 39 additions and 25 deletions.
Original file line number Diff line number Diff line change
@@ -1,9 +1,14 @@
package com.lambdaworks.redis;

import java.lang.reflect.Field;
import java.lang.reflect.InvocationTargetException;
import java.lang.reflect.Method;
import java.util.concurrent.TimeUnit;

import com.google.common.base.Equivalence;
import com.google.common.cache.CacheBuilder;
import com.google.common.cache.CacheLoader;
import com.google.common.cache.LoadingCache;
import com.google.common.reflect.AbstractInvocationHandler;
import com.lambdaworks.redis.protocol.RedisCommand;

Expand All @@ -21,11 +26,20 @@ class FutureSyncInvocationHandler<K, V> extends AbstractInvocationHandler {
private final RedisChannelHandler<K, V> connection;
protected long timeout;
protected TimeUnit unit;
private LoadingCache<Method, Method> methodCache;

public FutureSyncInvocationHandler(RedisChannelHandler<K, V> connection) {
public FutureSyncInvocationHandler(final RedisChannelHandler<K, V> connection) {
this.connection = connection;
this.timeout = connection.timeout;
this.unit = connection.unit;

methodCache = CacheBuilder.newBuilder().build(new CacheLoader<Method, Method>() {
@Override
public Method load(Method key) throws Exception {
return connection.getClass().getMethod(key.getName(), key.getParameterTypes());
}
});

}

/**
Expand All @@ -44,8 +58,7 @@ protected Object handleInvocation(Object proxy, Method method, Object[] args) th
return null;
}

Method targetMethod = connection.getClass().getMethod(method.getName(), method.getParameterTypes());

Method targetMethod = methodCache.get(method);
Object result = targetMethod.invoke(connection, args);

if (result instanceof RedisCommand) {
Expand All @@ -55,7 +68,6 @@ protected Object handleInvocation(Object proxy, Method method, Object[] args) th
return null;
}
}

return LettuceFutures.await(command, timeout, unit);
}

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,9 @@
import java.lang.reflect.Method;
import java.util.Set;

import com.google.common.cache.CacheBuilder;
import com.google.common.cache.CacheLoader;
import com.google.common.cache.LoadingCache;
import com.google.common.collect.ImmutableSet;
import com.google.common.reflect.AbstractInvocationHandler;

Expand All @@ -19,10 +22,17 @@ class PooledConnectionInvocationHandler<T> extends AbstractInvocationHandler {

private T connection;
private final RedisConnectionPool<T> pool;
private final LoadingCache<Method, Method> methodCache;

public PooledConnectionInvocationHandler(T connection, RedisConnectionPool<T> pool) {
public PooledConnectionInvocationHandler(final T connection, RedisConnectionPool<T> pool) {
this.connection = connection;
this.pool = pool;
methodCache = CacheBuilder.newBuilder().build(new CacheLoader<Method, Method>() {
@Override
public Method load(Method key) throws Exception {
return connection.getClass().getMethod(key.getName(), key.getParameterTypes());
}
});
}

@SuppressWarnings("unchecked")
Expand All @@ -42,7 +52,8 @@ protected Object handleInvocation(Object proxy, Method method, Object[] args) th
return null;
}

Method targetMethod = connection.getClass().getMethod(method.getName(), method.getParameterTypes());
Method targetMethod = methodCache.get(method);

try {
return targetMethod.invoke(connection, args);
} catch (InvocationTargetException e) {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,9 @@
import java.util.Map;
import java.util.concurrent.ConcurrentHashMap;

import com.google.common.cache.CacheBuilder;
import com.google.common.cache.CacheLoader;
import com.google.common.cache.LoadingCache;
import com.google.common.reflect.AbstractInvocationHandler;
import com.lambdaworks.redis.RedisConnectionPool;
import com.lambdaworks.redis.RedisException;
Expand All @@ -17,7 +20,12 @@
public class TransparentPoolingInvocationHandler<T> extends AbstractInvocationHandler {

private RedisConnectionPool<T> pool;
private final Map<Method, Method> methodCache = new ConcurrentHashMap<Method, Method>();
private final LoadingCache<Method, Method> methodCache = CacheBuilder.newBuilder().build(new CacheLoader<Method, Method>() {
@Override
public Method load(Method key) throws Exception {
return pool.getComponentType().getMethod(key.getName(), key.getParameterTypes());
}
});

public TransparentPoolingInvocationHandler(RedisConnectionPool<T> pool) {
this.pool = pool;
Expand All @@ -26,7 +34,7 @@ public TransparentPoolingInvocationHandler(RedisConnectionPool<T> pool) {
@Override
protected Object handleInvocation(Object proxy, Method method, Object[] args) throws Throwable {

Method targetMethod = getMethod(method);
Method targetMethod = methodCache.get(method);

if (pool == null) {
throw new RedisException("Connection pool is closed");
Expand All @@ -40,29 +48,12 @@ protected Object handleInvocation(Object proxy, Method method, Object[] args) th

T connection = pool.allocateConnection();
try {

return targetMethod.invoke(connection, args);
} finally {
pool.freeConnection(connection);
}
}

/**
* Lookup the target method using a cache.
*
* @param method source method
* @return the target method
* @throws NoSuchMethodException
*/
private Method getMethod(Method method) throws NoSuchMethodException {
Method targetMethod = methodCache.get(method);
if (targetMethod == null) {
targetMethod = pool.getComponentType().getMethod(method.getName(), method.getParameterTypes());
methodCache.put(method, targetMethod);
}
return targetMethod;
}

public RedisConnectionPool<T> getPool() {
return pool;
}
Expand Down

0 comments on commit c5f48c2

Please sign in to comment.