001 /* 002 * Licensed to the Apache Software Foundation (ASF) under one or more 003 * contributor license agreements. See the NOTICE file distributed with 004 * this work for additional information regarding copyright ownership. 005 * The ASF licenses this file to You under the Apache License, Version 2.0 006 * (the "License"); you may not use this file except in compliance with 007 * the License. You may obtain a copy of the License at 008 * 009 * http://www.apache.org/licenses/LICENSE-2.0 010 * 011 * Unless required by applicable law or agreed to in writing, software 012 * distributed under the License is distributed on an "AS IS" BASIS, 013 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 014 * See the License for the specific language governing permissions and 015 * limitations under the License. 016 */ 017 018 package org.apache.commons.performance.pool; 019 020 import java.util.logging.Logger; 021 import org.apache.commons.dbcp.AbandonedConfig; 022 import org.apache.commons.dbcp.AbandonedObjectPool; 023 import org.apache.commons.pool.impl.GenericObjectPool; 024 import org.apache.commons.pool.impl.StackObjectPool; 025 import org.apache.commons.pool.impl.SoftReferenceObjectPool; 026 import org.apache.commons.pool.impl.GenericKeyedObjectPool; 027 import org.apache.commons.pool.impl.StackKeyedObjectPool; 028 import org.apache.commons.performance.ConfigurationException; 029 import org.apache.commons.performance.ClientThread; 030 import org.apache.commons.performance.LoadGenerator; 031 import org.apache.commons.performance.Statistics; 032 033 /** 034 * Configurable load / performance tester for commons pool. 035 * Uses Commons Digester to parse and load configuration and spawns 036 * PoolClientThread instances to generate load and gather statistics. 037 * 038 */ 039 public class PoolSoak extends LoadGenerator { 040 041 // Pool instances 042 private GenericObjectPool genericObjectPool; 043 private GenericKeyedObjectPool genericKeyedObjectPool; 044 private StackObjectPool stackObjectPool; 045 private SoftReferenceObjectPool softReferenceObjectPool; 046 private StackKeyedObjectPool stackKeyedObjectPool; 047 048 // Pool properties 049 private String poolType; 050 private int maxActive; // maxActive for GOP, maxTotal for GKOP 051 private int maxActivePerKey; // maxActive for GKOP 052 private int maxIdle; 053 private int minIdle; 054 private long maxWait; 055 private byte exhaustedAction; 056 private boolean testOnBorrow; 057 private boolean testOnReturn; 058 private long timeBetweenEvictions; 059 private int testsPerEviction; 060 private long idleTimeout; 061 private boolean testWhileIdle; 062 private AbandonedConfig abandonedConfig = new AbandonedConfig(); 063 private boolean lifo; 064 private double samplingRate; 065 066 // WaiterFactory properties 067 private long activateLatency; 068 private long destroyLatency; 069 private long makeLatency; 070 private long passivateLatency; 071 private long validateLatency; 072 private long waiterLatency; 073 074 /** 075 * Add pool configuration to parameters loaded by super. 076 * Also set config file name. 077 */ 078 protected void configure() throws Exception { 079 super.configure(); 080 digester.addCallMethod("configuration/factory", 081 "configureFactory", 6); 082 digester.addCallParam( 083 "configuration/factory/activate-latency", 0); 084 digester.addCallParam( 085 "configuration/factory/destroy-latency", 1); 086 digester.addCallParam( 087 "configuration/factory/make-latency", 2); 088 digester.addCallParam( 089 "configuration/factory/passivate-latency", 3); 090 digester.addCallParam( 091 "configuration/factory/validate-latency", 4); 092 digester.addCallParam( 093 "configuration/factory/waiter-latency", 5); 094 digester.addCallMethod("configuration/pool", 095 "configurePool", 15); 096 digester.addCallParam( 097 "configuration/pool/max-active", 0); 098 digester.addCallParam( 099 "configuration/pool/max-active-per-key", 1); 100 digester.addCallParam( 101 "configuration/pool/max-idle", 2); 102 digester.addCallParam( 103 "configuration/pool/min-idle", 3); 104 digester.addCallParam( 105 "configuration/pool/max-wait", 4); 106 digester.addCallParam( 107 "configuration/pool/exhausted-action", 5); 108 digester.addCallParam( 109 "configuration/pool/test-on-borrow", 6); 110 digester.addCallParam( 111 "configuration/pool/test-on-return", 7); 112 digester.addCallParam( 113 "configuration/pool/time-between-evictions", 8); 114 digester.addCallParam( 115 "configuration/pool/tests-per-eviction", 9); 116 digester.addCallParam( 117 "configuration/pool/idle-timeout", 10); 118 digester.addCallParam( 119 "configuration/pool/test-while-idle", 11); 120 digester.addCallParam( 121 "configuration/pool/lifo", 12); 122 digester.addCallParam( 123 "configuration/pool/type", 13); 124 digester.addCallParam( 125 "configuration/pool/sampling-rate", 14); 126 digester.addCallMethod("configuration/abandoned-config", 127 "configureAbandonedConfig", 3); 128 digester.addCallParam( 129 "configuration/abandoned-config/log-abandoned", 0); 130 digester.addCallParam( 131 "configuration/abandoned-config/remove-abandoned", 1); 132 digester.addCallParam( 133 "configuration/abandoned-config/abandoned-timeout", 2); 134 135 this.configFile = "config-pool.xml"; 136 137 } 138 139 /** 140 * Create object pool and factory 141 */ 142 protected void init() throws Exception { 143 // Create factory 144 WaiterFactory factory = new WaiterFactory(activateLatency, destroyLatency, 145 makeLatency, passivateLatency, validateLatency, waiterLatency, 146 maxActive, maxActivePerKey); 147 148 // Create object pool 149 if (poolType.equals("GenericObjectPool")) { 150 genericObjectPool = new GenericObjectPool(factory); 151 genericObjectPool.setMaxActive(maxActive); 152 genericObjectPool.setWhenExhaustedAction(exhaustedAction); 153 genericObjectPool.setMaxWait(maxWait); 154 genericObjectPool.setMaxIdle(maxIdle); 155 genericObjectPool.setMinIdle(minIdle); 156 genericObjectPool.setTestOnBorrow(testOnBorrow); 157 genericObjectPool.setTestOnReturn(testOnReturn); 158 genericObjectPool.setTimeBetweenEvictionRunsMillis( 159 timeBetweenEvictions); 160 genericObjectPool.setNumTestsPerEvictionRun(testsPerEviction); 161 genericObjectPool.setMinEvictableIdleTimeMillis(idleTimeout); 162 genericObjectPool.setTestWhileIdle(testWhileIdle); 163 //genericObjectPool.setLifo(lifo); 164 } else if (poolType.equals("AbandonedObjectPool")) { 165 genericObjectPool = new AbandonedObjectPool(null,abandonedConfig); 166 genericObjectPool.setMaxActive(maxActive); 167 genericObjectPool.setWhenExhaustedAction(exhaustedAction); 168 genericObjectPool.setMaxWait(maxWait); 169 genericObjectPool.setMaxIdle(maxIdle); 170 genericObjectPool.setMinIdle(minIdle); 171 genericObjectPool.setTestOnBorrow(testOnBorrow); 172 genericObjectPool.setTestOnReturn(testOnReturn); 173 genericObjectPool.setTimeBetweenEvictionRunsMillis( 174 timeBetweenEvictions); 175 genericObjectPool.setNumTestsPerEvictionRun(testsPerEviction); 176 genericObjectPool.setMinEvictableIdleTimeMillis(idleTimeout); 177 genericObjectPool.setTestWhileIdle(testWhileIdle); 178 //genericObjectPool.setLifo(lifo); 179 genericObjectPool.setFactory(factory); 180 } else if (poolType.equals("GenericKeyedObjectPool")) { 181 genericKeyedObjectPool = new GenericKeyedObjectPool(); 182 genericKeyedObjectPool.setMaxActive(maxActivePerKey); 183 genericKeyedObjectPool.setMaxTotal(maxActive); 184 genericKeyedObjectPool.setWhenExhaustedAction(exhaustedAction); 185 genericKeyedObjectPool.setMaxWait(maxWait); 186 genericKeyedObjectPool.setMaxIdle(maxIdle); 187 genericKeyedObjectPool.setMinIdle(minIdle); 188 genericKeyedObjectPool.setTestOnBorrow(testOnBorrow); 189 genericKeyedObjectPool.setTestOnReturn(testOnReturn); 190 genericKeyedObjectPool.setTimeBetweenEvictionRunsMillis( 191 timeBetweenEvictions); 192 genericKeyedObjectPool.setNumTestsPerEvictionRun(testsPerEviction); 193 genericKeyedObjectPool.setMinEvictableIdleTimeMillis(idleTimeout); 194 genericKeyedObjectPool.setTestWhileIdle(testWhileIdle); 195 //genericKeyedObjectPool.setLifo(lifo); 196 genericKeyedObjectPool.setFactory(factory); 197 } else if (poolType.equals("StackObjectPool")) { 198 stackObjectPool = new StackObjectPool(); 199 stackObjectPool.setFactory(factory); 200 } else if (poolType.equals("SoftReferenceObjectPool")) { 201 softReferenceObjectPool = new SoftReferenceObjectPool(); 202 softReferenceObjectPool.setFactory(factory); 203 } else if (poolType.equals("StackKeyedObjectPool")) { 204 stackKeyedObjectPool = new StackKeyedObjectPool(); 205 stackKeyedObjectPool.setFactory(factory); 206 } else { 207 throw new ConfigurationException( 208 "invalid pool type configuration: " + poolType); 209 } 210 211 logger.info("Initialized pool with properties: "); 212 logger.info(" poolTypeT: " + poolType); 213 logger.info(" exhaustedAction: " + exhaustedAction); 214 logger.info(" maxActive: " + maxActive); 215 logger.info(" maxActivePerKey: " + maxActivePerKey); 216 logger.info(" maxIdle: " + maxIdle); 217 logger.info(" minIdle: " + minIdle); 218 logger.info(" testOnBorrow: " + testOnBorrow); 219 logger.info(" testWhileIdle: " + testWhileIdle); 220 logger.info(" timeBetweenEvictions: " + timeBetweenEvictions); 221 logger.info(" testsPerEviction: " + testsPerEviction); 222 logger.info(" idleTimeout: " + idleTimeout); 223 logger.info(" lifo: " + lifo); 224 logger.info(" abandonedConfig: "); 225 logger.info(" logAbandoned: " + 226 abandonedConfig.getLogAbandoned()); 227 logger.info(" removeAbandoned: " + 228 abandonedConfig.getRemoveAbandoned()); 229 logger.info(" abandonedTimeout: " + 230 abandonedConfig.getRemoveAbandonedTimeout()); 231 } 232 233 /** 234 * Close object pool 235 */ 236 protected void cleanUp() throws Exception { 237 if (genericObjectPool != null) { 238 genericObjectPool.close(); 239 } 240 if (genericKeyedObjectPool != null) { 241 genericKeyedObjectPool.close(); 242 } 243 if (stackObjectPool != null) { 244 stackObjectPool.close(); 245 } 246 if (softReferenceObjectPool != null) { 247 softReferenceObjectPool.close(); 248 } 249 if (stackKeyedObjectPool != null) { 250 stackKeyedObjectPool.close(); 251 } 252 } 253 254 /** 255 * Create and return a PoolClientThread 256 */ 257 protected ClientThread makeClientThread(long iterations, long minDelay, 258 long maxDelay, double sigma, String delayType, long rampPeriod, 259 long peakPeriod, long troughPeriod, String cycleType, 260 String rampType, Logger logger, Statistics stats) { 261 if (poolType.equals("GenericObjectPool")) { 262 return new PoolClientThread(iterations, minDelay, maxDelay, 263 sigma, delayType, rampPeriod, peakPeriod, troughPeriod, 264 cycleType, rampType, logger, stats, genericObjectPool, 265 samplingRate); 266 } 267 if (poolType.equals("GenericKeyedObjectPool")) { 268 return new PoolClientThread(iterations, minDelay, maxDelay, 269 sigma, delayType, rampPeriod, peakPeriod, troughPeriod, 270 cycleType, rampType, logger, stats, 271 genericKeyedObjectPool, samplingRate); 272 } 273 if (poolType.equals("StackKeyedObjectPool")) { 274 return new PoolClientThread(iterations, minDelay, maxDelay, 275 sigma, delayType, rampPeriod, peakPeriod, troughPeriod, 276 cycleType, rampType, logger, stats, 277 stackKeyedObjectPool, samplingRate); 278 } 279 if (poolType.equals("StackObjectPool")) { 280 return new PoolClientThread(iterations, minDelay, maxDelay, 281 sigma, delayType, rampPeriod, peakPeriod, troughPeriod, 282 cycleType, rampType, logger, stats, 283 stackObjectPool, samplingRate); 284 } 285 if (poolType.equals("SoftReferenceObjectPool")) { 286 return new PoolClientThread(iterations, minDelay, maxDelay, 287 sigma, delayType, rampPeriod, peakPeriod, troughPeriod, 288 cycleType, rampType, logger, stats, 289 softReferenceObjectPool, samplingRate); 290 } 291 return null; 292 } 293 294 // ------------------------------------------------------------------------ 295 // Configuration methods specific to this LoadGenerator invoked by Digester 296 // when superclass execute calls digerster.parse. 297 // ------------------------------------------------------------------------ 298 public void configureFactory(String activateLatency, String destroyLatency, 299 String makeLatency, String passivateLatency, String validateLatency, 300 String waiterLatency) { 301 302 this.activateLatency = Long.parseLong(activateLatency); 303 this.destroyLatency = Long.parseLong(destroyLatency); 304 this.makeLatency = Long.parseLong(makeLatency); 305 this.passivateLatency = Long.parseLong(passivateLatency); 306 this.validateLatency = Long.parseLong(validateLatency); 307 this.waiterLatency = Long.parseLong(waiterLatency); 308 } 309 310 public void configurePool(String maxActive, String maxActivePerKey, 311 String maxIdle, String minIdle, String maxWait, 312 String exhaustedAction, String testOnBorrow, 313 String testOnReturn, String timeBetweenEvictions, 314 String testsPerEviction, String idleTimeout, 315 String testWhileIdle, String lifo, String type, String samplingRate) 316 throws ConfigurationException { 317 this.maxActive = Integer.parseInt(maxActive); 318 this.maxActivePerKey = Integer.parseInt(maxActivePerKey); 319 this.maxIdle = Integer.parseInt(maxIdle); 320 this.minIdle = Integer.parseInt(minIdle); 321 this.maxWait = Long.parseLong(maxWait); 322 this.testOnBorrow = Boolean.parseBoolean(testOnBorrow); 323 this.testOnReturn = Boolean.parseBoolean(testOnReturn); 324 this.timeBetweenEvictions = Long.parseLong(timeBetweenEvictions); 325 this.testsPerEviction = Integer.parseInt(testsPerEviction); 326 this.idleTimeout = Long.parseLong(idleTimeout); 327 this.testWhileIdle = Boolean.parseBoolean(testWhileIdle); 328 this.lifo = Boolean.parseBoolean(lifo); 329 this.poolType = type; 330 if (exhaustedAction.equals("block")) { 331 this.exhaustedAction = GenericObjectPool.WHEN_EXHAUSTED_BLOCK; 332 } else if (exhaustedAction.equals("fail")) { 333 this.exhaustedAction = GenericObjectPool.WHEN_EXHAUSTED_FAIL; 334 } else if (exhaustedAction.equals("grow")) { 335 this.exhaustedAction = GenericObjectPool.WHEN_EXHAUSTED_GROW; 336 } else { 337 throw new ConfigurationException( 338 "Bad configuration setting for exhausted action: " 339 + exhaustedAction); 340 } 341 this.samplingRate = Double.parseDouble(samplingRate); 342 } 343 344 public void configureAbandonedConfig(String logAbandoned, 345 String removeAbandoned, String abandonedTimeout) { 346 abandonedConfig.setLogAbandoned(Boolean.parseBoolean(logAbandoned)); 347 abandonedConfig.setRemoveAbandoned( 348 Boolean.parseBoolean(removeAbandoned)); 349 abandonedConfig.setRemoveAbandonedTimeout( 350 Integer.parseInt(abandonedTimeout)); 351 } 352 353 // Pool getters for unit tests 354 protected GenericObjectPool getGenericObjectPool() { 355 return genericObjectPool; 356 } 357 358 protected GenericKeyedObjectPool getGenericKeyedObjectPool() { 359 return genericKeyedObjectPool; 360 } 361 362 }