1 5 package com.tctest; 6 7 import com.tc.object.config.ConfigVisitor; 8 import com.tc.object.config.DSOClientConfigHelper; 9 import com.tc.object.config.TransparencyClassSpec; 10 import com.tc.simulator.app.ApplicationConfig; 11 import com.tc.simulator.listener.ListenerProvider; 12 import com.tc.util.Assert; 13 import com.tc.util.DebugUtil; 14 import com.tctest.restart.system.ObjectDataRestartTestApp; 15 import com.tctest.runner.AbstractErrorCatchingTransparentApp; 16 17 import java.security.SecureRandom ; 18 import java.text.DateFormat ; 19 import java.text.SimpleDateFormat ; 20 import java.util.Date ; 21 import java.util.HashMap ; 22 import java.util.Map ; 23 import java.util.Random ; 24 import java.util.Vector ; 25 26 30 public class ClientMemoryReaperTestApp extends AbstractErrorCatchingTransparentApp { 31 public static final String SYNCHRONOUS_WRITE = "synch-write"; 32 33 private static final long OBJECT_COUNT = 2000; 34 private static final long MINIMUM_MEM_NEEDED = 60 * 1024 * 1024; 35 private static final int MEMORY_BLOCKS = 1024 * 1024; 36 37 final Map root = new HashMap (); 38 final Vector unusedBytes = new Vector (); 39 static long maxDepth = 1; 40 static int transient_mem_blocks_size = 0; 41 42 public ClientMemoryReaperTestApp(String appId, ApplicationConfig cfg, ListenerProvider listenerProvider) { 43 super(appId, cfg, listenerProvider); 44 } 45 46 public static void visitL1DSOConfig(ConfigVisitor visitor, DSOClientConfigHelper config) { 47 visitL1DSOConfig(visitor, config, new HashMap ()); 48 } 49 50 public static void visitL1DSOConfig(ConfigVisitor visitor, DSOClientConfigHelper config, Map optionalAttributes) { 51 DebugUtil.DEBUG = true; 52 53 boolean isSynchronousWrite = false; 54 if (optionalAttributes.size() > 0) { 55 isSynchronousWrite = Boolean.valueOf((String ) optionalAttributes.get(ObjectDataRestartTestApp.SYNCHRONOUS_WRITE)) 56 .booleanValue(); 57 } 58 59 String testClass = ClientMemoryReaperTestApp.class.getName(); 60 TransparencyClassSpec spec = config.getOrCreateSpec(testClass); 61 spec.addRoot("root", "root"); 62 String methodExpression = "* " + testClass + ".getNode(..)"; 63 config.addReadAutolock(methodExpression); 64 methodExpression = "* " + testClass + ".putNode(..)"; 65 addWriteAutolock(config, isSynchronousWrite, methodExpression); 66 methodExpression = "* " + testClass + ".addNode(..)"; 67 addWriteAutolock(config, isSynchronousWrite, methodExpression); 68 69 testClass = ClientMemoryReaperTestApp.Node.class.getName(); 70 spec = config.getOrCreateSpec(testClass); 71 config.addTransient(testClass, "transientBytes"); 72 73 DebugUtil.DEBUG = false; 74 } 75 76 private static void addWriteAutolock(DSOClientConfigHelper config, boolean isSynchronousWrite, String methodPattern) { 77 if (isSynchronousWrite) { 78 config.addSynchronousWriteAutolock(methodPattern); 79 debugPrintln("***** doing a synchronous write"); 80 } else { 81 config.addWriteAutolock(methodPattern); 82 } 83 } 84 85 private static void debugPrintln(String s) { 86 if (DebugUtil.DEBUG) { 87 System.err.println(s); 88 } 89 } 90 91 public void runTest() { 92 log("App Id = " + getApplicationId() + " participation count = " + getParticipantCount() + " intensity = " 93 + getIntensity()); 94 95 if (false) initHeap(); 97 initTransientMemBlockSize(); 98 99 long objectCount = 0; 100 log("Objects to Create = " + OBJECT_COUNT); 101 final SecureRandom sr = new SecureRandom (); 102 long seed = sr.nextLong(); 103 log(" Seed for Random = " + seed); 104 Random r = new Random (seed); 105 106 int topLevelObjectCount = (int) (OBJECT_COUNT / 50); 107 while (objectCount++ <= OBJECT_COUNT) { 108 Object myKey = new Integer (r.nextInt(topLevelObjectCount)); 109 Node n = getNode(myKey); 110 if (n == null) { 111 putNode(myKey, new Node(objectCount)); 112 } else { 113 addNode(n, new Node(objectCount)); 114 } 115 if (objectCount % 100 == 0) { 116 log("Objects created = " + objectCount); 117 } 118 } 119 log("Done !!"); 120 } 121 122 private static synchronized void initTransientMemBlockSize() { 123 if (transient_mem_blocks_size > 0) { 124 log("Transient memory block size is already initialized to " + transient_mem_blocks_size); 125 return; 126 } 127 Runtime runtime = Runtime.getRuntime(); 128 long max_memory = runtime.maxMemory(); 129 if (max_memory == Long.MAX_VALUE) { 130 throw new AssertionError ("This test is memory sensitive. Please specify the max memory using -Xmx option. " 132 + "Currently Max Memory is " + max_memory); 133 } 134 log("Max memory is " + max_memory); 135 transient_mem_blocks_size = (int) ((max_memory * 50) / (512 * 1024)); log("Transient memory block size is " + transient_mem_blocks_size); 137 } 138 139 private void initHeap() { 140 Runtime runtime = Runtime.getRuntime(); 141 long max_memory = runtime.maxMemory(); 142 if (max_memory == Long.MAX_VALUE || max_memory < MINIMUM_MEM_NEEDED) { 143 throw new AssertionError ("This test is memory sensitive. Please specify the max memory using -Xmx option. " 145 + " Ideal value for this test is >= " + MINIMUM_MEM_NEEDED 146 + ". Currently Max Memory is " + max_memory); 147 } 148 log("Max memory is " + max_memory); 149 long totalAllocations = 0; 150 synchronized (unusedBytes) { 152 while (max_memory > (runtime.totalMemory() + MINIMUM_MEM_NEEDED / 2) || runtime.freeMemory() > MINIMUM_MEM_NEEDED) { 153 final byte[] unused = new byte[MEMORY_BLOCKS]; 154 unusedBytes.add(unused); 155 totalAllocations += MEMORY_BLOCKS; 156 log("Allocated " + unused.length + " bytes. Free memory = " + runtime.freeMemory() + ". Total memory = " 157 + runtime.totalMemory()); 158 } 159 } 160 log("Total bytes allocated = " + totalAllocations); 161 } 162 163 static DateFormat formatter = new SimpleDateFormat ("hh:mm:ss,S"); 164 165 private static void log(String message) { 166 System.err.println(Thread.currentThread().getName() + " :: " 167 + formatter.format(new Date (System.currentTimeMillis())) + " : " + message); 168 } 169 170 private void addNode(Node rootNode, Node node) { 171 synchronized (rootNode) { 172 rootNode.add(node); 173 } 175 } 176 177 private synchronized static void setMaxDepth(long depth) { 178 if (maxDepth < depth) { 179 maxDepth = depth; 180 if (maxDepth % 10 == 0) { 181 log("Max Depth reached : " + maxDepth); 182 } 183 } 184 } 185 186 private void putNode(Object myKey, Node n) { 187 synchronized (root) { 188 root.put(myKey, n); 189 } 190 } 191 192 private Node getNode(Object myKey) { 193 synchronized (root) { 194 return (Node) root.get(myKey); 195 } 196 } 197 198 private static final class Node { 199 final long id; long lastAccess; 203 long level; 204 205 206 byte[] transientBytes = new byte[transient_mem_blocks_size]; 207 208 Node odd; 209 Node even; 210 211 Node(long id) { 212 this.id = id; 213 this.level = 0; 214 this.lastAccess = System.currentTimeMillis(); 215 } 216 217 void add(Node c) { 218 this.lastAccess = System.currentTimeMillis(); 219 if (this.transientBytes == null) { 220 this.transientBytes = new byte[transient_mem_blocks_size]; 222 } 223 Assert.assertFalse(this == c); 224 if (c.id % 2 == 1) { 225 if (odd == null) { 226 odd = c; 227 c.level = this.level + 1; 228 setMaxDepth(c.level); 229 } else { 230 odd.add(c); 231 } 232 } else { 233 if (even == null) { 234 even = c; 235 c.level = this.level + 1; 236 setMaxDepth(c.level); 237 } else { 238 even.add(c); 239 } 240 } 241 } 242 243 public String toString() { 244 return "Node(" + id + ") : level = " + level + " : odd = " + (odd == null) + " : even = " + (even == null); 245 } 246 247 } 248 249 } 250 | Popular Tags |