From 918405ec0274055004e4fd953b9672df296f3c19 Mon Sep 17 00:00:00 2001 From: Par Winzell Date: Sat, 24 Jan 2009 18:53:42 +0000 Subject: [PATCH] While investigating problems, add much paranoid profiling. Also let's do an explicit keyset copy during enumeration rather than the fancy concurrent hashmaps and iterable mappings. Finally, let's fully synchronize the other maps we're using. --- .../com/samskivert/depot/EHCacheAdapter.java | 76 +++++++++++++------ 1 file changed, 54 insertions(+), 22 deletions(-) diff --git a/src/java/com/samskivert/depot/EHCacheAdapter.java b/src/java/com/samskivert/depot/EHCacheAdapter.java index 397334e..535ad2a 100644 --- a/src/java/com/samskivert/depot/EHCacheAdapter.java +++ b/src/java/com/samskivert/depot/EHCacheAdapter.java @@ -25,9 +25,6 @@ import java.util.Collections; import java.util.Map; import java.util.Set; -import com.google.common.base.Function; -import com.google.common.base.Predicates; -import com.google.common.collect.Iterables; import com.google.common.collect.Maps; import com.google.common.collect.Sets; import com.samskivert.util.Tuple; @@ -44,7 +41,7 @@ import static com.samskivert.depot.Log.log; * in one {@link Ehcache}. All (cacheId, key) combinations within one category is stuffed into the * same {@link Ehcache}, and all elements are cached under {@link EHCacheKey}, which basically * wraps just such a tuple. - * + * * Thus there are currently only three Ehcaches in play, called 'depotRecord', 'depotKeyset', and * 'depotResult'. These must be defined in your ehcache.xml configuration. If you use distributed * replication/invalidation, you should replicate updates and removes but not puts nor @@ -72,17 +69,25 @@ public class EHCacheAdapter // from CacheAdapter public CachedValue lookup (String cacheId, Serializable key) { + long now = System.currentTimeMillis(); @SuppressWarnings("unchecked") EHCacheBin bin = (EHCacheBin) _bins.get(cacheId); if (bin == null) { return null; } - return lookup(bin.getCache(), cacheId, key); + CachedValue result = lookup(bin.getCache(), cacheId, key); + long dT = System.currentTimeMillis() - now; + if (dT > 50) { + log.warning("Aii! A simple ehcache lookup took over 50 ms!", "cacheId", cacheId, + "key", key, "dT", dT); + } + return result; } // from CacheAdapter public void store (CacheCategory category, String cacheId, Serializable key, T value) { + long now = System.currentTimeMillis(); Ehcache cache = _categories.get(category); if (cache == null) { throw new IllegalArgumentException("Unknown category: " + category); @@ -94,35 +99,57 @@ public class EHCacheAdapter _bins.put(cacheId, bin); } bin.getCache().put(new Element(new EHCacheKey(cacheId, key), value != null ? value : NULL)); + long dT = System.currentTimeMillis() - now; + if (dT > 50) { + log.warning("Aii! A simple ehcache store took over 50 ms!", "cacheId", cacheId, + "key", key, "dT", dT); + } } // from CacheAdapter public void remove (String cacheId, Serializable key) { + long now = System.currentTimeMillis(); EHCacheBin bin = _bins.get(cacheId); if (bin != null) { bin.getCache().remove(new EHCacheKey(cacheId, key)); } + long dT = System.currentTimeMillis() - now; + if (dT > 50) { + log.warning("Aii! A simple ehcache remove took over 50 ms!", "cacheId", cacheId, + "key", key, "dT", dT); + } } // from CacheAdapter public Iterable>> enumerate (final String cacheId) { + if (_slowEnumerations > 5) { + return Collections.emptySet(); + } + long now = System.currentTimeMillis(); + EHCacheBin bin = _bins.get(cacheId); if (bin == null) { return Collections.emptySet(); } - final Ehcache cache = bin.getCache(); - Iterable>> tuples = Iterables.transform( - bin.getKeys(), new Function>> () { - public Tuple> apply (Serializable key) { - CachedValue value = lookup(cache, cacheId, key); - return (value != null) ? Tuple.newTuple(key, value) : null; - } - }); - - return Iterables.filter(tuples, Predicates.notNull()); + Set>> result = Sets.newHashSet(); + Ehcache cache = bin.getCache(); + + for (Serializable key : bin.getKeys()) { + CachedValue value = lookup(cache, cacheId, key); + if (value != null) { + result.add(Tuple.newTuple(key, value)); + } + } + long dT = System.currentTimeMillis() - now; + if (dT > 50) { + _slowEnumerations ++; + log.warning("Aii! Enumerating cache took a long time!", "cacheId", cacheId, "dT", dT, + "cacheSize", result.size(), "disabled", _slowEnumerations > 5); + } + return result; } // from CacheAdapter @@ -163,8 +190,13 @@ public class EHCacheAdapter return cache; } - protected Map _categories = Maps.newConcurrentHashMap(); - protected Map> _bins = Maps.newConcurrentHashMap(); + // TODO: To be removed when we're done investigating potential sluggishness + protected int _slowEnumerations = 0; + + protected Map _categories = + Collections.synchronizedMap(Maps.newHashMap()); + protected Map> _bins = + Collections.synchronizedMap(Maps.> newHashMap()); protected CacheEventListener _cacheEventListener = new CacheEventListener() { public Object clone () throws CloneNotSupportedException { @@ -214,7 +246,7 @@ public class EHCacheAdapter bin.addKey(key.getCacheKey()); } }; - + protected static class EHCacheBin { public EHCacheBin (Ehcache cache, String id) @@ -242,7 +274,7 @@ public class EHCacheAdapter { return _cache; } - + protected Ehcache _cache; protected String _id; @@ -268,18 +300,18 @@ public class EHCacheAdapter public String getCacheId () { return _id; } - + public Serializable getCacheKey () { return _key; } - + @Override public String toString () { return "[" + _id + ", " + _key + "]"; } - + @Override public int hashCode () {