1 5 package com.tc.object.cache; 6 7 import com.tc.logging.TCLogger; 8 import com.tc.logging.TCLogging; 9 import com.tc.runtime.MemoryEventType; 10 import com.tc.runtime.MemoryEventsListener; 11 import com.tc.runtime.MemoryUsage; 12 import com.tc.runtime.TCMemoryManagerImpl; 13 import com.tc.util.Assert; 14 import com.tc.util.State; 15 16 import java.util.List ; 17 18 public class CacheManager implements MemoryEventsListener { 19 20 private static final TCLogger logger = TCLogging.getLogger(CacheManager.class); 21 22 private static final State INIT = new State("INIT"); 23 private static final State PROCESSING = new State("PROCESSING"); 24 private static final State COMPLETE = new State("COMPLETE"); 25 26 private final Evictable evictable; 27 private final CacheConfig config; 28 private final TCMemoryManagerImpl memoryManager; 29 30 private int calculatedCacheSize = 0; 31 private CacheStatistics lastStat = null; 32 33 public CacheManager(Evictable evictable, CacheConfig config) { 34 this.evictable = evictable; 35 this.config = config; 36 this.memoryManager = new TCMemoryManagerImpl(config.getUsedThreshold(), config.getUsedCriticalThreshold(), config 37 .getSleepInterval(), config.getLeastCount(), config.isOnlyOldGenMonitored()); 38 this.memoryManager.registerForMemoryEvents(this); 39 } 40 41 public void memoryUsed(MemoryEventType type, MemoryUsage usage) { 42 CacheStatistics cp = new CacheStatistics(type, usage); 43 evictable.evictCache(cp); 44 cp.validate(); 45 addLastStat(cp); 46 } 47 48 private void addLastStat(CacheStatistics cp) { 50 this.lastStat = cp; 51 } 52 53 private final class CacheStatistics implements CacheStats { 54 private final MemoryEventType type; 55 private final MemoryUsage usage; 56 57 private int countBefore; 58 private int countAfter; 59 private int evicted; 60 private boolean objectsGCed = false; 61 private int toEvict; 62 private long startTime; 63 private State state = INIT; 64 65 public CacheStatistics(MemoryEventType type, MemoryUsage usage) { 66 this.type = type; 67 this.usage = usage; 68 } 69 70 public void validate() { 71 if (state == PROCESSING) { 72 throw new AssertionError (this + " : Object Evicted is not called. This indicates a bug in the software !"); 74 } 75 } 76 77 public int getObjectCountToEvict(int currentCount) { 78 startTime = System.currentTimeMillis(); 79 countBefore = currentCount; 80 adjustCachedObjectCount(currentCount); 81 toEvict = computeObjects2Evict(currentCount); 82 if (toEvict < 0 || toEvict > currentCount) { 83 throw new AssertionError ("Computed Object to evict is out of range : toEvict = " + toEvict + " currentCount = " 85 + currentCount + " " + this); 86 } 87 if (toEvict > 0) { 88 state = PROCESSING; 89 } 90 if (config.isLoggingEnabled()) { 91 logger.info("Asking to evict " + toEvict + " current size = " + currentCount + " calculated cache size = " 92 + calculatedCacheSize + " heap used = " + usage.getUsedPercentage() + " % gc count = " 93 + usage.getCollectionCount()); 94 } 95 return this.toEvict; 96 } 97 98 private void adjustCachedObjectCount(int currentCount) { 106 if (type == MemoryEventType.BELOW_THRESHOLD || lastStat == null 107 || lastStat.usage.getCollectionCount() < usage.getCollectionCount() 108 || (usage.getCollectionCount() < 0 && lastStat.usage.getUsedMemory() > usage.getUsedMemory())) { 109 double used = usage.getUsedPercentage(); 110 double threshold = config.getUsedThreshold(); 111 Assert.assertTrue((type == MemoryEventType.BELOW_THRESHOLD && threshold >= used) || threshold <= used); 112 if (used > 0) calculatedCacheSize = (int) (currentCount * (threshold / used)); 113 } 114 } 115 116 public void objectEvicted(int evictedCount, int currentCount, List targetObjects4GC) { 117 this.evicted = evictedCount; 118 this.countAfter = currentCount; 119 state = COMPLETE; 120 if (config.isLoggingEnabled()) { 122 logger.info("Evicted " + evictedCount + " current Size = " + currentCount + " new objects created = " 123 + getNewObjectsCount() + " time taken = " + (System.currentTimeMillis() - startTime) + " ms"); 124 } 125 } 126 127 private int getNewObjectsCount() { 128 return countAfter - (countBefore - evicted); 129 } 130 131 private int computeObjects2Evict(int currentCount) { 134 if (type == MemoryEventType.BELOW_THRESHOLD || calculatedCacheSize > currentCount) { return 0; } 135 int overshoot = currentCount - calculatedCacheSize; 136 if (overshoot <= 0) return 0; 137 int objects2Evict = overshoot + ((calculatedCacheSize * config.getPercentageToEvict()) / 100); 138 return objects2Evict; 139 } 140 141 public String toString() { 142 return "CacheStats[ type = " + type + ",\n\t usage = " + usage + ",\n\t countBefore = " + countBefore 143 + ", toEvict = " + toEvict + ", evicted = " + evicted + ", countAfter = " + countAfter 144 + ", objectsGCed = " + objectsGCed + ",\n\t state = " + state + "]"; 145 } 146 } 147 148 } 149 | Popular Tags |