OPENJPA-1739 Added additional metrics to cache statistics and updated instrumentation.

git-svn-id: https://svn.apache.org/repos/asf/openjpa/trunk@984896 13f79535-47bb-0310-9956-ffa450edef68
This commit is contained in:
Jeremy Bauer 2010-08-12 18:18:43 +00:00
parent 7bfc33e468
commit a36ace562b
10 changed files with 291 additions and 53 deletions

View File

@ -82,6 +82,14 @@ public class TestJMXPlatformMBeans extends AbstractPersistenceTestCase {
assertTrue(oemf.getCache().contains(CachedEntity.class, id)); assertTrue(oemf.getCache().contains(CachedEntity.class, id));
ce = oem.find(CachedEntity.class, id); ce = oem.find(CachedEntity.class, id);
assertTrue(dci.getHitCount() > 0);
try {
assertTrue(dci.getHitCount(CachedEntity.class.getName()) > 0);
} catch (ClassNotFoundException e) {
fail("CachedEntity class not found");
}
assertTrue(dci.getWriteCount() > 0);
assertTrue(dci.classNames().contains(CachedEntity.class.getName()));
// Thread out to do out-of-band MBean-based validation. This could // Thread out to do out-of-band MBean-based validation. This could
// have been done on the same thread, but threading out makes for a // have been done on the same thread, but threading out makes for a
// more realistic test. // more realistic test.
@ -271,6 +279,9 @@ public class TestJMXPlatformMBeans extends AbstractPersistenceTestCase {
assertTrue(clsHitCount > 0); assertTrue(clsHitCount > 0);
assertTrue(clsReadCount > 0); assertTrue(clsReadCount > 0);
assertTrue(clsWriteCount > 0); assertTrue(clsWriteCount > 0);
Set<String> classNames = (Set<String>)mbs.invoke(on, "classNames", null, null);
assertNotNull(classNames);
assertTrue(classNames.contains(CachedEntity.class.getName()));
// Invoke the reset method and recollect stats // Invoke the reset method and recollect stats
mbs.invoke(on, "reset", null, null); mbs.invoke(on, "reset", null, null);
hitCount = (Long)mbs.getAttribute(on, "HitCount"); hitCount = (Long)mbs.getAttribute(on, "HitCount");

View File

@ -152,7 +152,11 @@ public class PreparedQueryCacheImpl implements PreparedQueryCache {
try { try {
if (_log != null && _log.isTraceEnabled()) if (_log != null && _log.isTraceEnabled())
_log.trace(_loc.get("prepared-query-invalidate", id)); _log.trace(_loc.get("prepared-query-invalidate", id));
return _delegate.remove(id) != null; boolean rc = _delegate.remove(id) != null;
if (_statsEnabled && rc) {
_stats.recordEviction(id);
}
return rc;
} finally { } finally {
unlock(false); unlock(false);
} }
@ -187,7 +191,11 @@ public class PreparedQueryCacheImpl implements PreparedQueryCache {
if (_log != null && _log.isTraceEnabled()) if (_log != null && _log.isTraceEnabled())
_log.trace(_loc.get("prepared-query-uncache", id, exclusion)); _log.trace(_loc.get("prepared-query-uncache", id, exclusion));
} }
return _delegate.remove(id); PreparedQuery pq = _delegate.remove(id);
if (_statsEnabled && pq != null) {
_stats.recordEviction(id);
}
return pq;
} finally { } finally {
unlock(false); unlock(false);
} }

View File

@ -40,8 +40,6 @@ import org.apache.openjpa.lib.log.Log;
import org.apache.openjpa.lib.util.Localizer; import org.apache.openjpa.lib.util.Localizer;
import org.apache.openjpa.lib.util.concurrent.AbstractConcurrentEventManager; import org.apache.openjpa.lib.util.concurrent.AbstractConcurrentEventManager;
import org.apache.openjpa.util.GeneralException; import org.apache.openjpa.util.GeneralException;
import org.apache.openjpa.util.OpenJPAException;
import serp.util.Strings; import serp.util.Strings;
/** /**
@ -235,6 +233,9 @@ public abstract class AbstractDataCache extends AbstractConcurrentEventManager
public DataCachePCData remove(Object key) { public DataCachePCData remove(Object key) {
DataCachePCData o = removeInternal(key); DataCachePCData o = removeInternal(key);
if (stats.isEnabled()) {
stats.newEvict(o == null ? null : o.getType());
}
if (o != null && o.isTimedOut()) if (o != null && o.isTimedOut())
o = null; o = null;
if (log.isTraceEnabled()) { if (log.isTraceEnabled()) {

View File

@ -187,6 +187,9 @@ public abstract class AbstractQueryCache
public QueryResult remove(QueryKey key) { public QueryResult remove(QueryKey key) {
QueryResult o = removeInternal(key); QueryResult o = removeInternal(key);
if (_statsEnabled) {
_stats.recordEviction(key);
}
if (o != null && o.isTimedOut()) if (o != null && o.isTimedOut())
o = null; o = null;
if (log.isTraceEnabled()) { if (log.isTraceEnabled()) {
@ -448,6 +451,10 @@ public abstract class AbstractQueryCache
return _name; return _name;
} }
public int count() {
return keySet().size();
}
/** /**
* A default implementation of query statistics for the Query result cache. * A default implementation of query statistics for the Query result cache.
* *
@ -463,9 +470,10 @@ public abstract class AbstractQueryCache
private static final float LOAD_FACTOR = 0.75f; private static final float LOAD_FACTOR = 0.75f;
private static final int CONCURRENCY = 16; private static final int CONCURRENCY = 16;
private static final int ARRAY_SIZE = 2; private static final int ARRAY_SIZE = 3;
private static final int READ = 0; private static final int READ = 0;
private static final int HIT = 1; private static final int HIT = 1;
private static final int EVICT = 2;
private long[] astat = new long[ARRAY_SIZE]; private long[] astat = new long[ARRAY_SIZE];
private long[] stat = new long[ARRAY_SIZE]; private long[] stat = new long[ARRAY_SIZE];
@ -510,6 +518,14 @@ public abstract class AbstractQueryCache
return getCount(astats, query, HIT); return getCount(astats, query, HIT);
} }
public long getEvictionCount() {
return stat[EVICT];
}
public long getTotalEvictionCount() {
return astat[EVICT];
}
private long getCount(Map<T, long[]> target, T query, int i) { private long getCount(Map<T, long[]> target, T query, int i) {
long[] row = target.get(query); long[] row = target.get(query);
return (row == null) ? 0 : row[i]; return (row == null) ? 0 : row[i];
@ -565,6 +581,12 @@ public abstract class AbstractQueryCache
addSample(query, HIT); addSample(query, HIT);
} }
public void recordEviction(T query) {
if (query == null)
return;
addSample(query, EVICT);
}
public void dump(PrintStream out) { public void dump(PrintStream out) {
String header = "Query Statistics starting from " + start; String header = "Query Statistics starting from " + start;
out.print(header); out.print(header);

View File

@ -22,6 +22,7 @@ import java.io.Serializable;
import java.util.Date; import java.util.Date;
import java.util.HashMap; import java.util.HashMap;
import java.util.Map; import java.util.Map;
import java.util.Set;
/** /**
* Counts number of read/write requests and hit ratio for a cache in total and * Counts number of read/write requests and hit ratio for a cache in total and
@ -74,34 +75,54 @@ public interface CacheStatistics extends Serializable {
/** /**
* Gets number of total read requests for the given class since last reset. * Gets number of total read requests for the given class since last reset.
*/ */
public long getReadCount(Class c); public long getReadCount(Class<?> c);
/** /**
* Gets number of total read requests that has been found in cache for the * Gets number of total read requests that has been found in cache for the
* given class since last reset. * given class since last reset.
*/ */
public long getHitCount(Class c); public long getHitCount(Class<?> c);
/** /**
* Gets number of total write requests for the given class since last reset. * Gets number of total write requests for the given class since last reset.
*/ */
public long getWriteCount(Class c); public long getWriteCount(Class<?> c);
/** /**
* Gets number of total read requests for the given class since start. * Gets number of total read requests for the given class since start.
*/ */
public long getTotalReadCount(Class c); public long getTotalReadCount(Class<?> c);
/** /**
* Gets number of total read requests that has been found in cache for the * Gets number of total read requests that has been found in cache for the
* given class since start. * given class since start.
*/ */
public long getTotalHitCount(Class c); public long getTotalHitCount(Class<?> c);
/** /**
* Gets number of total write requests for the given class since start. * Gets number of total write requests for the given class since start.
*/ */
public long getTotalWriteCount(Class c); public long getTotalWriteCount(Class<?> c);
/**
* Gets number of total evictions since last reset.
*/
public long getEvictionCount();
/**
* Gets number of total evictions for the given class since last reset.
*/
public long getEvictionCount(Class<?> c);
/**
* Gets number of total evictions in cache since start.
*/
public long getTotalEvictionCount();
/**
* Gets number of total evictions for the given class since start.
*/
public long getTotalEvictionCount(Class<?> c);
/** /**
* Gets the time of last reset. * Gets the time of last reset.
@ -123,15 +144,22 @@ public interface CacheStatistics extends Serializable {
*/ */
public boolean isEnabled(); public boolean isEnabled();
/**
* Returns the classes being tracked.
* @return
*/
public Set<Class<?>> classNames();
/** /**
* A default implementation. * A default implementation.
* *
*/ */
public static class Default implements CacheStatistics { public static class Default implements CacheStatistics {
private long[] astat = new long[3]; private static final int ARRAY_SIZE = 4;
private long[] stat = new long[3]; private long[] astat = new long[ARRAY_SIZE];
private Map<Class, long[]> stats = new HashMap<Class, long[]>(); private long[] stat = new long[ARRAY_SIZE];
private Map<Class, long[]> astats = new HashMap<Class, long[]>(); private Map<Class<?>, long[]> stats = new HashMap<Class<?>, long[]>();
private Map<Class<?>, long[]> astats = new HashMap<Class<?>, long[]>();
private Date start = new Date(); private Date start = new Date();
private Date since = new Date(); private Date since = new Date();
private boolean enabled = false; private boolean enabled = false;
@ -139,6 +167,7 @@ public interface CacheStatistics extends Serializable {
private static final int READ = 0; private static final int READ = 0;
private static final int HIT = 1; private static final int HIT = 1;
private static final int WRITE = 2; private static final int WRITE = 2;
private static final int EVICT = 3;
public long getReadCount() { public long getReadCount() {
return stat[READ]; return stat[READ];
@ -152,6 +181,10 @@ public interface CacheStatistics extends Serializable {
return stat[WRITE]; return stat[WRITE];
} }
public long getEvictionCount() {
return stat[EVICT];
}
public long getTotalReadCount() { public long getTotalReadCount() {
return astat[READ]; return astat[READ];
} }
@ -164,31 +197,43 @@ public interface CacheStatistics extends Serializable {
return astat[WRITE]; return astat[WRITE];
} }
public long getReadCount(Class c) { public long getTotalEvictionCount() {
return astat[EVICT];
}
public long getReadCount(Class<?> c) {
return getCount(stats, c, READ); return getCount(stats, c, READ);
} }
public long getHitCount(Class c) { public long getHitCount(Class<?> c) {
return getCount(stats, c, HIT); return getCount(stats, c, HIT);
} }
public long getWriteCount(Class c) { public long getWriteCount(Class<?> c) {
return getCount(stats, c, WRITE); return getCount(stats, c, WRITE);
} }
public long getTotalReadCount(Class c) { public long getEvictionCount(Class<?> c) {
return getCount(stats, c, EVICT);
}
public long getTotalReadCount(Class<?> c) {
return getCount(astats, c, READ); return getCount(astats, c, READ);
} }
public long getTotalHitCount(Class c) { public long getTotalHitCount(Class<?> c) {
return getCount(astats, c, HIT); return getCount(astats, c, HIT);
} }
public long getTotalWriteCount(Class c) { public long getTotalWriteCount(Class<?> c) {
return getCount(astats, c, WRITE); return getCount(astats, c, WRITE);
} }
private long getCount(Map<Class, long[]> target, Class c, int index) { public long getTotalEvictionCount(Class<?> c) {
return getCount(astats, c, EVICT);
}
private long getCount(Map<Class<?>, long[]> target, Class<?> c, int index) {
long[] row = target.get(c); long[] row = target.get(c);
return (row == null) ? 0 : row[index]; return (row == null) ? 0 : row[index];
} }
@ -202,7 +247,7 @@ public interface CacheStatistics extends Serializable {
} }
public void reset() { public void reset() {
stat = new long[3]; stat = new long[ARRAY_SIZE];
stats.clear(); stats.clear();
since = new Date(); since = new Date();
} }
@ -216,7 +261,7 @@ public interface CacheStatistics extends Serializable {
void disable() { void disable() {
enabled = false; enabled = false;
} }
void newGet(Class cls, boolean hit) { void newGet(Class<?> cls, boolean hit) {
cls = (cls == null) ? Object.class : cls; cls = (cls == null) ? Object.class : cls;
addSample(cls, READ); addSample(cls, READ);
if (hit) { if (hit) {
@ -224,25 +269,34 @@ public interface CacheStatistics extends Serializable {
} }
} }
void newPut(Class cls) { void newPut(Class<?> cls) {
cls = (cls == null) ? Object.class : cls; cls = (cls == null) ? Object.class : cls;
addSample(cls, WRITE); addSample(cls, WRITE);
} }
private void addSample(Class c, int index) { void newEvict(Class<?> cls) {
cls = (cls == null) ? Object.class : cls;
addSample(cls, EVICT);
}
private void addSample(Class<?> c, int index) {
stat[index]++; stat[index]++;
astat[index]++; astat[index]++;
addSample(stats, c, index); addSample(stats, c, index);
addSample(astats, c, index); addSample(astats, c, index);
} }
private void addSample(Map<Class, long[]> target, Class c, int index) { private void addSample(Map<Class<?>, long[]> target, Class<?> c, int index) {
long[] row = target.get(c); long[] row = target.get(c);
if (row == null) { if (row == null) {
row = new long[3]; row = new long[ARRAY_SIZE];
} }
row[index]++; row[index]++;
target.put(c, row); target.put(c, row);
} }
public Set<Class<?>> classNames() {
return astats.keySet();
}
} }
} }

View File

@ -18,7 +18,10 @@
*/ */
package org.apache.openjpa.instrumentation; package org.apache.openjpa.instrumentation;
import java.util.Collections;
import java.util.Date; import java.util.Date;
import java.util.HashSet;
import java.util.Set;
import org.apache.openjpa.datacache.CacheStatistics; import org.apache.openjpa.datacache.CacheStatistics;
import org.apache.openjpa.datacache.DataCache; import org.apache.openjpa.datacache.DataCache;
@ -152,22 +155,6 @@ public abstract class AbstractDataCacheInstrument extends AbstractInstrument
return null; return null;
} }
public long getEvictionCount() {
CacheStatistics stats = getStatistics();
// TODO : Implement eviction count in data cache stats
// if (stats != null)
// return stats.getEvictionCount();
return NO_STATS;
}
public long getTotalEvictionCount() {
CacheStatistics stats = getStatistics();
// TODO : Implement eviction count in data cache stats
// if (stats != null)
// return stats.getTotalEvictionCount();
return NO_STATS;
}
public String getConfigId() { public String getConfigId() {
return _configID; return _configID;
} }
@ -231,8 +218,63 @@ public abstract class AbstractDataCacheInstrument extends AbstractInstrument
return NO_STATS; return NO_STATS;
} }
public long getEvictionCount() {
CacheStatistics stats = getStatistics();
if (stats != null)
return stats.getEvictionCount();
return NO_STATS;
}
public long getEvictionCount(String className)
throws ClassNotFoundException {
Class<?> clazz = Class.forName(className);
return getEvictionCount(clazz);
}
public long getEvictionCount(Class<?> c) {
CacheStatistics stats = getStatistics();
if (stats != null)
return stats.getEvictionCount(c);
return NO_STATS;
}
public long getTotalEvictionCount() {
CacheStatistics stats = getStatistics();
if (stats != null)
return stats.getTotalEvictionCount();
return NO_STATS;
}
public long getTotalEvictionCount(String className)
throws ClassNotFoundException {
Class<?> clazz = Class.forName(className);
return getTotalEvictionCount(clazz);
}
public long getTotalEvictionCount(Class<?> c) {
CacheStatistics stats = getStatistics();
if (stats != null)
return stats.getTotalEvictionCount(c);
return NO_STATS;
}
@SuppressWarnings("unchecked")
public Set<String> classNames() {
CacheStatistics stats = getStatistics();
if (stats != null) {
Set<String> classNames = new HashSet<String>();
Set<Class<?>> clazzNames = stats.classNames();
for (Class<?> clazz : clazzNames) {
if (clazz != null) {
classNames.add(clazz.getName());
}
}
return classNames;
}
return Collections.EMPTY_SET;
}
public InstrumentationLevel getLevel() { public InstrumentationLevel getLevel() {
return InstrumentationLevel.FACTORY; return InstrumentationLevel.FACTORY;
} }
} }

View File

@ -22,6 +22,7 @@ import java.util.Date;
import java.util.HashSet; import java.util.HashSet;
import java.util.Set; import java.util.Set;
import org.apache.openjpa.datacache.AbstractQueryCache;
import org.apache.openjpa.datacache.QueryCache; import org.apache.openjpa.datacache.QueryCache;
import org.apache.openjpa.datacache.QueryKey; import org.apache.openjpa.datacache.QueryKey;
import org.apache.openjpa.kernel.QueryStatistics; import org.apache.openjpa.kernel.QueryStatistics;
@ -159,6 +160,26 @@ public abstract class AbstractQueryCacheInstrument extends AbstractInstrument
return null; return null;
} }
/**
* Returns number of total evictions since last reset
*/
public long getEvictionCount() {
QueryStatistics<QueryKey> stats = getStatistics();
if (stats != null)
return stats.getEvictionCount();
return NO_STATS;
}
/**
* Returns number of total eviction requests since start.
*/
public long getTotalEvictionCount() {
QueryStatistics<QueryKey> stats = getStatistics();
if (stats != null)
return stats.getTotalEvictionCount();
return NO_STATS;
}
/** /**
* Returns all query keys currently tracked in the cache. * Returns all query keys currently tracked in the cache.
* @return * @return
@ -185,6 +206,17 @@ public abstract class AbstractQueryCacheInstrument extends AbstractInstrument
return null; return null;
} }
public long count() {
if (_qc == null) {
return NO_STATS;
}
if (_qc instanceof AbstractQueryCache) {
AbstractQueryCache aqc = (AbstractQueryCache)_qc;
return aqc.count();
}
return NO_STATS;
}
public InstrumentationLevel getLevel() { public InstrumentationLevel getLevel() {
return InstrumentationLevel.FACTORY; return InstrumentationLevel.FACTORY;
} }

View File

@ -19,6 +19,7 @@
package org.apache.openjpa.instrumentation; package org.apache.openjpa.instrumentation;
import java.util.Date; import java.util.Date;
import java.util.Set;
/** /**
* Interface for providing instrumented data cache metrics and operations. * Interface for providing instrumented data cache metrics and operations.
@ -119,4 +120,9 @@ public interface DataCacheInstrument {
* Returns date cache statistics collection started. * Returns date cache statistics collection started.
*/ */
public Date startDate(); public Date startDate();
/**
* Returns the names of classes currently tracked in the cache.
*/
public Set<String> classNames();
} }

View File

@ -32,7 +32,8 @@ public interface QueryCacheInstrument {
public long getTotalExecutionCount(); public long getTotalExecutionCount();
/** /**
* Returns number of total exec requests since start. * Returns number of total exec requests since start for
* the specified string-ified query key.
*/ */
public long getTotalExecutionCount(String queryKey); public long getTotalExecutionCount(String queryKey);
@ -42,7 +43,8 @@ public interface QueryCacheInstrument {
public long getExecutionCount(); public long getExecutionCount();
/** /**
* Returns number of total execution requests since last reset * Returns number of total execution requests since last reset for
* the specified string-ified query key.
*/ */
public long getExecutionCount(String queryKey); public long getExecutionCount(String queryKey);
@ -54,7 +56,7 @@ public interface QueryCacheInstrument {
/** /**
* Returns number of total read requests that have been found in cache since * Returns number of total read requests that have been found in cache since
* last reset. * last reset for the specified string-ified query key.
*/ */
public long getHitCount(String queryKey); public long getHitCount(String queryKey);
@ -64,7 +66,8 @@ public interface QueryCacheInstrument {
public long getTotalHitCount(); public long getTotalHitCount();
/** /**
* Returns number of total read requests that has been found since start. * Returns number of total read requests that has been found since start for
* the specified string-ified query key.
*/ */
public long getTotalHitCount(String queryKey); public long getTotalHitCount(String queryKey);
@ -84,8 +87,25 @@ public interface QueryCacheInstrument {
public Date startDate(); public Date startDate();
/** /**
* Returns all query keys currently in the cache. * Returns all the string-ified keys for query results in the cache.
* @return * @return
*/ */
public Set<String> queryKeys(); public Set<String> queryKeys();
/**
* Returns number of total evictions since last reset
*/
public long getEvictionCount();
/**
* Returns number of total eviction requests since start.
*/
public long getTotalEvictionCount();
/**
* Returns the number of total entries in the cache.
* @return entries
*/
public long count();
} }

View File

@ -52,6 +52,11 @@ public interface QueryStatistics<T> extends Serializable {
*/ */
void recordExecution(T query); void recordExecution(T query);
/**
* Record that the given query has been evicted.
*/
void recordEviction(T query);
/** /**
* Gets number of total query execution since last reset. * Gets number of total query execution since last reset.
*/ */
@ -95,6 +100,16 @@ public interface QueryStatistics<T> extends Serializable {
public long getTotalHitCount(T query); public long getTotalHitCount(T query);
/** /**
* Gets number of total query evictions since last reset.
*/
public long getEvictionCount();
/**
* Gets number of total query evictions since start.
*/
public long getTotalEvictionCount();
/**
* Gets the time of last reset. * Gets the time of last reset.
*/ */
public Date since(); public Date since();
@ -131,9 +146,10 @@ public interface QueryStatistics<T> extends Serializable {
private static final float LOAD_FACTOR = 0.75f; private static final float LOAD_FACTOR = 0.75f;
private static final int CONCURRENCY = 16; private static final int CONCURRENCY = 16;
private static final int ARRAY_SIZE = 2; private static final int ARRAY_SIZE = 3;
private static final int READ = 0; private static final int READ = 0;
private static final int HIT = 1; private static final int HIT = 1;
private static final int EVICT = 2;
private long[] astat = new long[ARRAY_SIZE]; private long[] astat = new long[ARRAY_SIZE];
private long[] stat = new long[ARRAY_SIZE]; private long[] stat = new long[ARRAY_SIZE];
@ -232,6 +248,13 @@ public interface QueryStatistics<T> extends Serializable {
addSample(query, HIT); addSample(query, HIT);
} }
public void recordEviction(T query) {
if (query == null) {
return;
}
addSample(query, EVICT);
}
public void dump(PrintStream out) { public void dump(PrintStream out) {
String header = "Query Statistics starting from " + start; String header = "Query Statistics starting from " + start;
out.print(header); out.print(header);
@ -267,6 +290,14 @@ public interface QueryStatistics<T> extends Serializable {
String toString(long[] row) { String toString(long[] row) {
return row[READ] + ":" + row[HIT] + "(" + pct(row[HIT], row[READ]) + "%)"; return row[READ] + ":" + row[HIT] + "(" + pct(row[HIT], row[READ]) + "%)";
} }
public long getEvictionCount() {
return stat[EVICT];
}
public long getTotalEvictionCount() {
return astat[EVICT];
}
} }
/** /**
@ -318,6 +349,14 @@ public interface QueryStatistics<T> extends Serializable {
return 0; return 0;
} }
public long getEvictionCount() {
return 0;
}
public long getTotalEvictionCount() {
return 0;
}
public Set<T> keys() { public Set<T> keys() {
return Collections.emptySet(); return Collections.emptySet();
} }
@ -337,6 +376,9 @@ public interface QueryStatistics<T> extends Serializable {
public Date start() { public Date start() {
return start; return start;
} }
public void recordEviction(T query) {
}
} }
} }