001: /*
002: * All content copyright (c) 2003-2006 Terracotta, Inc., except as may otherwise be noted in a separate copyright
003: * notice. All rights reserved.
004: */
005: package com.tc.object.cache;
006:
007: import com.tc.object.ObjectID;
008:
009: import java.util.Collection;
010: import java.util.Iterator;
011: import java.util.LinkedHashMap;
012: import java.util.Random;
013:
014: public class LFUEvictionPolicyTest extends LRUEvictionPolicyTest {
015:
016: public void tests() throws Exception {
017: int capacity = 50;
018: int maxObjects = capacity * 2;
019: EvictionPolicy slc = createNewCache(capacity);
020:
021: LinkedHashMap cacheables = new LinkedHashMap();
022: Random r = new Random();
023: for (int i = 1; i < 20000; i++) {
024: ObjectID id = new ObjectID(r.nextInt(maxObjects));
025: TestCacheable tc = (TestCacheable) cacheables.get(id);
026: if (tc == null) {
027: tc = new TestCacheable(id);
028: cacheables.put(id, tc);
029: boolean full = slc.add(tc);
030: if (full && cacheables.size() <= capacity) {
031: throw new AssertionError(
032: "Cache is full when capacity = " + capacity
033: + "and size () = "
034: + cacheables.size());
035: } else if (!full && cacheables.size() > capacity) {
036: // Formatter
037: throw new AssertionError(
038: "Cache is Not full when capacity = "
039: + capacity + "and size () = "
040: + cacheables.size());
041: }
042: } else {
043: int accessed = tc.accessCount();
044: slc.markReferenced(tc);
045: if (++accessed != tc.accessCount()) {
046: throw new AssertionError(
047: "Accessed Count Mismatch : "
048: + tc.accessCount() + " Expected : "
049: + accessed);
050: }
051: }
052: }
053:
054: while (cacheables.size() > capacity) {
055: Collection rc = slc.getRemovalCandidates(10);
056: int maxAccessed = -1;
057: for (Iterator i = rc.iterator(); i.hasNext();) {
058: TestCacheable tc = (TestCacheable) i.next();
059: if (maxAccessed < tc.accessCount()) {
060: maxAccessed = tc.accessCount();
061: }
062: slc.remove(tc);
063: assertTrue(cacheables.remove(tc.getObjectID()) == tc);
064: }
065: System.err.println("Max Accessed is : " + maxAccessed);
066: int errorThreshold = 0;
067: for (Iterator i = cacheables.values().iterator(); i
068: .hasNext();) {
069: TestCacheable tc = (TestCacheable) i.next();
070: assertFalse(rc.contains(tc));
071: if (tc.accessCount() < maxAccessed) {
072: System.err.println("WARNING : maxAccessed : "
073: + maxAccessed + " tc.accessCount() "
074: + tc.accessCount());
075: // throw new AssertionError("Got an Object that is accessed more that one available in cache");
076: errorThreshold++;
077: }
078: }
079: // Commenting this as this is assertion is not valid anymore.
080: // if (errorThreshold >= rc.size()) {
081: // throw new AssertionError("Beyond Error Threshold : " + errorThreshold);
082: // }
083: if (errorThreshold > 0) {
084: System.err.println("WARNING : errorThreshold is "
085: + errorThreshold);
086: }
087: }
088: }
089:
090: public void testLargeCacheEviction() throws Exception {
091: if (true) {
092: System.err
093: .println("This test (testLargeCacheEviction) is DISABLED.");
094: return;
095: }
096: int capacity = 3500000;
097: int count = capacity + 500000;
098: EvictionPolicy slc = createNewCache(capacity);
099:
100: LinkedHashMap cacheables = new LinkedHashMap();
101: for (int i = 1; i < count; i++) {
102: ObjectID id = new ObjectID(i);
103: TestCacheable tc = new TestCacheable(id, i);
104: cacheables.put(id, tc);
105: slc.add(tc);
106: }
107:
108: int s_range = 0, e_range = 0;
109: while (cacheables.size() > capacity) {
110: long start = System.currentTimeMillis();
111: Collection rc = slc.getRemovalCandidates(10000);
112: s_range = e_range;
113: e_range = e_range + rc.size();
114: long end = System.currentTimeMillis();
115: System.err.println("Time take for evicting " + rc.size()
116: + " from " + cacheables.size() + " = "
117: + (end - start) + " ms");
118: for (Iterator i = rc.iterator(); i.hasNext();) {
119: TestCacheable tc = (TestCacheable) i.next();
120: if (s_range > tc.accessCount()
121: || e_range < tc.accessCount()) {
122: // XXX:: This is not an error anymore since every call to getRemovalCandidates affects the accessCount
123: System.err
124: .println("Access Count falls in the wrong for "
125: + tc
126: + " range : "
127: + tc.accessCount()
128: + " range = "
129: + s_range + " , " + e_range);
130: }
131: slc.remove(tc);
132: assertTrue(cacheables.remove(tc.getObjectID()) == tc);
133: }
134: }
135: }
136:
137: public EvictionPolicy createNewCache(int cacheSize) {
138: return new LFUEvictionPolicy(cacheSize);
139: }
140:
141: }
|