1 6 package org.logicalcobwebs.proxool; 7 8 import org.apache.commons.logging.Log; 9 import org.apache.commons.logging.LogFactory; 10 import org.logicalcobwebs.proxool.admin.StatisticsIF; 11 import org.logicalcobwebs.proxool.admin.StatisticsListenerIF; 12 import org.logicalcobwebs.proxool.admin.SnapshotIF; 13 14 import java.sql.Connection ; 15 import java.sql.DriverManager ; 16 import java.sql.SQLException ; 17 import java.sql.Statement ; 18 import java.util.Properties ; 19 import java.text.DecimalFormat ; 20 21 29 public class PerformanceTest extends AbstractProxoolTest implements StatisticsListenerIF { 30 31 private static final Log LOG = LogFactory.getLog(PerformanceTest.class); 32 33 private static DecimalFormat millisecondsFormat = new DecimalFormat ("0.00"); 34 35 private Thread waitingThead; 36 37 private StatisticsIF statistics; 38 private static final int PERIOD = 5; 39 private static final int COUNT = 6; 40 private long servedCount; 41 42 public PerformanceTest(String s) { 43 super(s); 44 } 45 46 50 public void testPerformance() throws ProxoolException, InterruptedException { 51 52 waitingThead = Thread.currentThread(); 53 54 String alias = "testPeformance"; 55 int threadCount = 20; 56 String url = TestHelper.buildProxoolUrl(alias, 57 TestConstants.HYPERSONIC_DRIVER, 58 TestConstants.HYPERSONIC_TEST_URL); 59 Properties info = new Properties (); 60 info.setProperty(ProxoolConstants.USER_PROPERTY, TestConstants.HYPERSONIC_USER); 61 info.setProperty(ProxoolConstants.PASSWORD_PROPERTY, TestConstants.HYPERSONIC_PASSWORD); 62 info.setProperty(ProxoolConstants.MINIMUM_CONNECTION_COUNT_PROPERTY, String.valueOf(threadCount)); 63 info.setProperty(ProxoolConstants.VERBOSE_PROPERTY, String.valueOf(Boolean.TRUE)); 64 info.setProperty(ProxoolConstants.MAXIMUM_CONNECTION_COUNT_PROPERTY, String.valueOf(threadCount)); 65 69 ProxoolFacade.registerConnectionPool(url, info); 70 73 74 doWait(); 75 76 AnnoyingConnector[] annoyingConnectors = new AnnoyingConnector[threadCount]; 77 for (int i = 0; i < annoyingConnectors.length; i++) { 78 annoyingConnectors[i] = new AnnoyingConnector(alias); 79 Thread t = new Thread (annoyingConnectors[i]); 80 t.start(); 81 } 82 83 for (int i = 0; i < COUNT; i++) { 84 doWait(); 85 } 86 87 for (int i = 0; i < annoyingConnectors.length; i++) { 88 annoyingConnectors[i].cancel(); 89 } 90 91 for (int i = 0; i < 5; i++) { 92 int activeConnectionCount = ProxoolFacade.getSnapshot(alias).getActiveConnectionCount(); 93 if (activeConnectionCount > 0) { 94 LOG.info("Waiting for 10 seconds for connections to become inactive (" + activeConnectionCount + ")"); 95 Thread.sleep(10000); 96 } else { 97 break; 98 } 99 } 100 101 final SnapshotIF snapshot = ProxoolFacade.getSnapshot(alias, true); 102 LOG.info("Active count: " + snapshot.getActiveConnectionCount()); 103 LOG.info("Available count: " + snapshot.getAvailableConnectionCount()); 104 ConnectionInfoIF[] cis = snapshot.getConnectionInfos(); 105 LOG.info("Found " + cis.length + " connetions with a detailed snapshot" + ""); 106 for (int i = 0; i < cis.length; i++) { 107 ConnectionInfoIF ci = cis[i]; 108 LOG.info("#" + ci.getId() + ": " + ci.getStatus() + ", lap=" + (ci.getTimeLastStopActive() - ci.getTimeLastStartActive())); 109 } 110 LOG.info("Served a total of " + ProxoolFacade.getSnapshot(alias).getServedCount()); 111 112 } 113 114 private void doWait() { 115 synchronized (Thread.currentThread()) { 116 try { 117 Thread.currentThread().wait(60000); 118 } catch (InterruptedException e) { 119 fail("Statistics didn't arrive as expected"); 120 } 121 } 122 } 123 124 public void statistics(String alias, StatisticsIF statistics) { 125 this.servedCount += statistics.getServedCount(); 126 this.statistics = statistics; 127 synchronized (waitingThead) { 128 waitingThead.notify(); 129 } 130 } 131 132 public void testSnapshotImpact() throws ProxoolException { 133 134 waitingThead = Thread.currentThread(); 135 136 String alias = "testPeformance"; 137 int threadCount = 10; 138 String url = TestHelper.buildProxoolUrl(alias, 139 TestConstants.HYPERSONIC_DRIVER, 140 TestConstants.HYPERSONIC_TEST_URL); 141 Properties info = new Properties (); 142 info.setProperty(ProxoolConstants.USER_PROPERTY, TestConstants.HYPERSONIC_USER); 143 info.setProperty(ProxoolConstants.PASSWORD_PROPERTY, TestConstants.HYPERSONIC_PASSWORD); 144 info.setProperty(ProxoolConstants.MINIMUM_CONNECTION_COUNT_PROPERTY, String.valueOf(threadCount)); 145 info.setProperty(ProxoolConstants.MAXIMUM_CONNECTION_COUNT_PROPERTY, String.valueOf(threadCount)); 146 info.setProperty(ProxoolConstants.STATISTICS_PROPERTY, String.valueOf(PERIOD) + "s"); 147 info.setProperty(ProxoolConstants.STATISTICS_LOG_LEVEL_PROPERTY, ProxoolConstants.STATISTICS_LOG_LEVEL_INFO); 148 info.setProperty(ProxoolConstants.VERBOSE_PROPERTY, String.valueOf(Boolean.TRUE)); 149 ProxoolFacade.registerConnectionPool(url, info); 150 ProxoolFacade.addStatisticsListener(alias, this); 151 DisagreeableSnapshotter disagreeableSnapshotter = new DisagreeableSnapshotter(alias); 152 new Thread (disagreeableSnapshotter).start(); 153 154 AnnoyingConnector[] annoyingConnectors = new AnnoyingConnector[threadCount]; 155 for (int i = 0; i < annoyingConnectors.length; i++) { 156 annoyingConnectors[i] = new AnnoyingConnector(alias); 157 Thread t = new Thread (annoyingConnectors[i]); 158 t.start(); 159 } 160 161 doWait(); 162 163 int servedCount = 0; 164 for (int i = 0; i < COUNT; i++) { 165 doWait(); 166 servedCount += statistics.getServedCount(); 167 assertTrue("disparityNoticed", !disagreeableSnapshotter.isDisparityNoticed()); 168 } 169 170 for (int i = 0; i < annoyingConnectors.length; i++) { 171 annoyingConnectors[i].cancel(); 172 } 173 disagreeableSnapshotter.cancel(); 174 175 long start = System.currentTimeMillis(); 176 while (System.currentTimeMillis() - start < 30000) { 177 int threadsRunning = 0; 178 for (int i = 0; i < annoyingConnectors.length; i++) { 179 if (annoyingConnectors[i].isRunning()) { 180 threadsRunning++; 181 } 182 } 183 if (disagreeableSnapshotter.isRunning()) { 184 threadsRunning++; 185 } 186 if (threadsRunning == 0) { 187 break; 188 } 189 } 190 191 192 assertTrue("disparityNoticed", !disagreeableSnapshotter.isDisparityNoticed()); 193 194 LOG.info("Served " + servedCount 195 + " at " + millisecondsFormat.format((double) (1000 * PERIOD * COUNT) / (double) servedCount) + " ms per connection"); 196 197 } 198 199 class DisagreeableSnapshotter implements Runnable { 200 201 private String alias; 202 203 private boolean cancelled; 204 205 private boolean disparityNoticed; 206 207 private boolean running; 208 209 public DisagreeableSnapshotter(String alias) { 210 this.alias = alias; 211 } 212 213 public void run() { 214 215 running = true; 216 int snapshotCount = 0; 217 while (!cancelled) { 218 try { 219 Thread.sleep(100); 220 } catch (InterruptedException e) { 221 LOG.error("Awoken", e); 222 } 223 try { 224 SnapshotIF s = ProxoolFacade.getSnapshot(alias, true); 225 int c1 = s.getActiveConnectionCount(); 226 int c2 = getCount(s.getConnectionInfos(), ConnectionInfoIF.STATUS_ACTIVE); 227 int v1 = s.getAvailableConnectionCount(); 228 int v2 = getCount(s.getConnectionInfos(), ConnectionInfoIF.STATUS_AVAILABLE); 229 int o1 = s.getOfflineConnectionCount(); 230 int o2 = getCount(s.getConnectionInfos(), ConnectionInfoIF.STATUS_OFFLINE); 231 if (c1 != c2 || v1 != v2 || o1 != o2) { 232 LOG.error("Disparity noticed. Active: " + c1 + (c1 == c2 ? " == " : " != ") + c2 233 + ", available: " + v1 + (v1 == v2 ? " == " : " != ") + v2 234 + ", offline: " + o1 + (o1 == o2 ? " == " : " != ") + o2); 235 disparityNoticed = true; 236 } 237 snapshotCount++; 238 } catch (ProxoolException e) { 239 LOG.error("Couldn't get snapshot", e); 240 } 241 } 242 LOG.info(snapshotCount + " snapshots taken"); 243 running = false; 244 } 245 246 public boolean isRunning() { 247 return running; 248 } 249 250 private int getCount(ConnectionInfoIF[] connectionInfos, int status) { 251 int count = 0; 252 for (int i = 0; i < connectionInfos.length; i++) { 253 if (connectionInfos[i].getStatus() == status) { 254 count++; 255 } 256 } 257 return count; 258 } 259 260 public boolean isDisparityNoticed() { 261 return disparityNoticed; 262 } 263 264 public void cancel() { 265 cancelled = true; 266 } 267 268 } 269 270 class AnnoyingConnector implements Runnable { 271 272 private String alias; 273 274 private boolean cancelled; 275 276 private int exceptionCount; 277 278 private boolean running = false; 279 280 public AnnoyingConnector(String alias) { 281 this.alias = alias; 282 } 283 284 public void run() { 285 running = true; 286 while (!cancelled) { 287 try { 288 Connection connection = null; 289 Statement s = null; 290 try { 291 connection = DriverManager.getConnection(TestHelper.buildProxoolUrl(alias)); 292 s = connection.createStatement(); 293 Thread.yield(); 294 } finally { 295 if (s != null) { 296 s.close(); 297 } 298 if (connection != null) { 299 connection.close(); 300 } 301 } 302 } catch (SQLException e) { 303 LOG.error(Thread.currentThread().getName(), e); 304 exceptionCount++; 305 } 306 } 307 running = false; 308 } 309 310 public boolean isRunning() { 311 return running; 312 } 313 314 public void cancel() { 315 cancelled = true; 316 } 317 318 public int getExceptionCount() { 319 return exceptionCount; 320 } 321 322 } 323 324 } 325 326 385 | Popular Tags |