1 4 package com.tc.runtime; 5 6 import com.tc.logging.TCLogger; 7 import com.tc.logging.TCLogging; 8 import com.tc.util.DebugUtil; 9 import com.tc.util.runtime.Os; 10 11 import java.util.ArrayList ; 12 import java.util.Iterator ; 13 import java.util.List ; 14 15 public class TCMemoryManagerImpl implements TCMemoryManager { 16 17 private static final TCLogger logger = TCLogging.getLogger(TCMemoryManagerImpl.class); 18 19 private final List listeners = new ArrayList (); 20 21 private final int threshold; 22 private final int criticalThreshold; 23 private final int leastCount; 24 private final long sleepInterval; 25 private final boolean monitorOldGenOnly; 26 27 private MemoryMonitor monitor; 28 29 public TCMemoryManagerImpl(int usedThreshold, int usedCriticalThreshold, long sleepInterval, int leastCount, 30 boolean monitorOldGenOnly) { 31 verifyInput(usedThreshold, usedCriticalThreshold, sleepInterval, leastCount); 32 this.monitorOldGenOnly = monitorOldGenOnly; 33 this.leastCount = leastCount; 34 this.threshold = usedThreshold; 35 this.criticalThreshold = usedCriticalThreshold; 36 this.sleepInterval = sleepInterval; 37 } 38 39 private void verifyInput(int usedT, int usedCT, long sleep, int lc) { 40 if (usedT <= 0 || usedT >= 100) { 41 throw new AssertionError ("Used Threshold should be > 0 && < 100 : " + usedT + " Outside range"); 43 } 44 if (usedCT <= 0 || usedCT >= 100) { 45 throw new AssertionError ("Critical Used Threshold should be > 0 && < 100 : " + usedCT + " Outside range"); 47 } 48 if (usedT > usedCT) { 49 throw new AssertionError ("Used Threshold should be <= Critical Used Threshold : " + usedT + " <= " + usedCT); 51 } 52 if (sleep <= 0) { 53 throw new AssertionError ("Sleep Interval cannot be <= 0 : sleep Interval = " + sleep); 55 } 56 if (lc <= 0 || lc >= 100) { 57 throw new AssertionError ("Least Count should be > 0 && < 100 : " + lc + " Outside range"); 59 } 60 } 61 62 public synchronized void registerForMemoryEvents(MemoryEventsListener listener) { 63 listeners.add(listener); 64 startMonitorIfNecessary(); 65 } 66 67 public synchronized void unregisterForMemoryEvents(MemoryEventsListener listener) { 68 listeners.remove(listener); 69 stopMonitorIfNecessary(); 70 } 71 72 private void stopMonitorIfNecessary() { 73 if (listeners.size() == 0 && monitor != null) { 74 monitor.stop(); 75 monitor = null; 76 } 77 } 78 79 private void startMonitorIfNecessary() { 80 if (listeners.size() > 0 && monitor == null) { 81 this.monitor = new MemoryMonitor(TCRuntime.getJVMMemoryManager(), this.sleepInterval, this.monitorOldGenOnly); 82 Thread t = new Thread (this.monitor); 83 t.setDaemon(true); 84 if (Os.isSolaris()) { 85 t.setPriority(Thread.MAX_PRIORITY); 86 t.setName("TC Memory Monitor(High Priority)"); 87 } else { 88 t.setName("TC Memory Monitor"); 89 } 90 t.start(); 91 } 92 } 93 94 private synchronized void fireMemoryEvent(MemoryEventType type, MemoryUsage mu) { 95 for (Iterator i = listeners.iterator(); i.hasNext();) { 96 MemoryEventsListener listener = (MemoryEventsListener) i.next(); 97 listener.memoryUsed(type, mu); 98 } 99 } 100 101 public class MemoryMonitor implements Runnable { 102 103 private final JVMMemoryManager manager; 104 private final boolean oldGen; 105 private volatile boolean run = true; 106 private int lastUsed; 107 private MemoryUsage lastReported; 108 private long sleepTime; 109 private MemoryEventType currentState; 110 111 public MemoryMonitor(JVMMemoryManager manager, long sleepInterval, boolean monitorOldGenOnly) { 112 this.manager = manager; 113 this.sleepTime = sleepInterval; 114 this.oldGen = monitorOldGenOnly && manager.isMemoryPoolMonitoringSupported(); 115 this.currentState = MemoryEventType.BELOW_THRESHOLD; 116 } 117 118 public void stop() { 119 run = false; 120 } 121 122 public void run() { 123 logger.debug("Starting Memory Monitor - sleep interval - " + sleepTime); 124 final boolean _oldGen = oldGen; 125 while (run) { 126 try { 127 Thread.sleep(sleepTime); 128 MemoryUsage mu = (_oldGen ? manager.getOldGenUsage() : manager.getMemoryUsage()); 129 if (DebugUtil.DEBUG) { 130 logger.info("Memory Usage is : " + mu); 131 } 132 reportUsage(mu); 133 adjust(mu); 134 } catch (Throwable t) { 135 logger.error(t); 136 } 137 } 138 logger.debug("Stopping Memory Monitor - sleep interval - " + sleepTime); 139 } 140 141 private void adjust(MemoryUsage mu) { 142 int usedPercentage = mu.getUsedPercentage(); 143 try { 144 if (lastUsed != 0 && lastUsed < usedPercentage) { 145 int diff = usedPercentage - lastUsed; 146 long l_sleep = this.sleepTime; 147 if (diff > leastCount * 1.5 && l_sleep > 1) { 148 this.sleepTime = Math.max(1, l_sleep * leastCount / diff); 150 logger.info("Sleep time changed to : " + this.sleepTime); 151 } else if (diff < leastCount * 0.5 && l_sleep < sleepInterval) { 152 this.sleepTime = Math.min(sleepInterval, l_sleep * leastCount / diff); 154 logger.info("Sleep time changed to : " + this.sleepTime); 155 } 156 } 157 } finally { 158 lastUsed = usedPercentage; 159 } 160 } 161 162 private void reportUsage(MemoryUsage mu) { 163 int usedPercentage = mu.getUsedPercentage(); 164 if (usedPercentage < threshold) { 165 if (currentState != MemoryEventType.BELOW_THRESHOLD) { 166 fire(MemoryEventType.BELOW_THRESHOLD, mu); 168 } 169 } else if (usedPercentage >= criticalThreshold) { 170 if (!oldGen || currentState != MemoryEventType.ABOVE_CRITICAL_THRESHOLD || isLeastCountReached(usedPercentage) 171 || isGCCompleted(mu)) { 172 fire(MemoryEventType.ABOVE_CRITICAL_THRESHOLD, mu); 175 } 176 } else if (currentState != MemoryEventType.ABOVE_THRESHOLD || isLeastCountReached(usedPercentage)) { 177 fire(MemoryEventType.ABOVE_THRESHOLD, mu); 178 } 179 } 180 181 private boolean isGCCompleted(MemoryUsage mu) { 182 return lastReported.getCollectionCount() < mu.getCollectionCount(); 183 } 184 185 private boolean isLeastCountReached(int usedPercentage) { 186 return (Math.abs(usedPercentage - lastReported.getUsedPercentage()) >= leastCount); 187 } 188 189 private void fire(MemoryEventType type, MemoryUsage mu) { 190 fireMemoryEvent(type, mu); 191 currentState = type; 192 lastReported = mu; 193 } 194 } 195 196 } 197 | Popular Tags |