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 */ 017package org.apache.activemq.tool.sampler; 018 019import java.util.concurrent.CountDownLatch; 020import java.util.concurrent.atomic.AtomicBoolean; 021 022import org.apache.activemq.tool.ClientRunBasis; 023import org.apache.activemq.tool.properties.AbstractObjectProperties; 024import org.apache.activemq.tool.reports.PerformanceReportWriter; 025import org.apache.commons.lang.Validate; 026import org.slf4j.Logger; 027import org.slf4j.LoggerFactory; 028 029public abstract class AbstractPerformanceSampler extends AbstractObjectProperties implements PerformanceSampler { 030 031 private final Logger log = LoggerFactory.getLogger(this.getClass()); 032 033 protected long rampUpPercent = 0; 034 protected long rampDownPercent = 0; 035 036 // the following are all optionally set; they are otherwise worked out at run time 037 protected Long rampUpTime; 038 protected Long rampDownTime; 039 protected Long duration; 040 041 protected long interval = 1000; // 1 sec 042 protected PerformanceReportWriter perfReportWriter; 043 protected PerformanceEventListener perfEventListener; 044 protected final AtomicBoolean isRunning = new AtomicBoolean(false); 045 protected CountDownLatch completionLatch; 046 protected long sampleIndex; 047 048 @Override 049 public Long getRampUpTime() { 050 return rampUpTime; 051 } 052 053 @Override 054 public void setRampUpTime(long rampUpTime) { 055 this.rampUpTime = rampUpTime; 056 } 057 058 @Override 059 public Long getRampDownTime() { 060 return rampDownTime; 061 } 062 063 @Override 064 public void setRampDownTime(long rampDownTime) { 065 this.rampDownTime = rampDownTime; 066 } 067 068 @Override 069 public Long getDuration() { 070 return duration; 071 } 072 073 @Override 074 public void setDuration(long duration) { 075 this.duration = duration; 076 } 077 078 @Override 079 public long getInterval() { 080 return interval; 081 } 082 083 @Override 084 public void setInterval(long interval) { 085 this.interval = interval; 086 } 087 088 @Override 089 public long getRampUpPercent() { 090 return rampUpPercent; 091 } 092 093 @Override 094 public void setRampUpPercent(long rampUpPercent) { 095 Validate.isTrue((rampUpPercent >= 0) && (rampUpPercent <= 100), "rampUpPercent must be a value between 0 and 100"); 096 this.rampUpPercent = rampUpPercent; 097 } 098 099 @Override 100 public long getRampDownPercent() { 101 return rampDownPercent; 102 } 103 104 @Override 105 public void setRampDownPercent(long rampDownPercent) { 106 Validate.isTrue((rampDownPercent >= 0) && (rampDownPercent < 100), "rampDownPercent must be a value between 0 and 99"); 107 this.rampDownPercent = rampDownPercent; 108 } 109 110 @Override 111 public PerformanceReportWriter getPerfReportWriter() { 112 return perfReportWriter; 113 } 114 115 @Override 116 public void setPerfReportWriter(PerformanceReportWriter perfReportWriter) { 117 this.perfReportWriter = perfReportWriter; 118 } 119 120 @Override 121 public PerformanceEventListener getPerfEventListener() { 122 return perfEventListener; 123 } 124 125 @Override 126 public void setPerfEventListener(PerformanceEventListener perfEventListener) { 127 this.perfEventListener = perfEventListener; 128 } 129 130 @Override 131 public void startSampler(CountDownLatch completionLatch, ClientRunBasis clientRunBasis, long clientRunDuration) { 132 Validate.notNull(clientRunBasis); 133 Validate.notNull(completionLatch); 134 135 if (clientRunBasis == ClientRunBasis.time) { 136 // override the default durations 137 // if the user has overridden a duration, then use that 138 duration = (duration == null) ? clientRunDuration : this.duration; 139 rampUpTime = (rampUpTime == null) ? (duration / 100 * rampUpPercent) : this.rampUpTime; 140 rampDownTime = (rampDownTime == null) ? (duration / 100 * rampDownPercent) : this.rampDownTime; 141 142 Validate.isTrue(duration >= (rampUpTime + rampDownTime), 143 "Ramp times (up: " + rampDownTime + ", down: " + rampDownTime + ") exceed the sampler duration (" + duration + ")"); 144 log.info("Sampling duration: {} ms, ramp up: {} ms, ramp down: {} ms", duration, rampUpTime, rampDownTime); 145 146 // spawn notifier thread to stop the sampler, taking ramp-down time into account 147 Thread notifier = new Thread(new RampDownNotifier(this)); 148 notifier.setName("RampDownNotifier[" + this.getClass().getSimpleName() + "]"); 149 notifier.start(); 150 } else { 151 log.info("Performance test running on count basis; ignoring duration and ramp times"); 152 setRampUpTime(0); 153 setRampDownTime(0); 154 } 155 156 this.completionLatch = completionLatch; 157 Thread t = new Thread(this); 158 t.setName(this.getClass().getSimpleName()); 159 t.start(); 160 isRunning.set(true); 161 } 162 163 @Override 164 public void finishSampling() { 165 isRunning.set(false); 166 } 167 168 @Override 169 public void run() { 170 try { 171 log.debug("Ramp up start"); 172 onRampUpStart(); 173 if (perfEventListener != null) { 174 perfEventListener.onRampUpStart(this); 175 } 176 177 if (rampUpTime > 0) { 178 try { 179 Thread.sleep(rampUpTime); 180 } catch (InterruptedException e) { 181 e.printStackTrace(); 182 } 183 } 184 185 log.debug("Sampler start"); 186 onSamplerStart(); 187 if (perfEventListener != null) { 188 perfEventListener.onSamplerStart(this); 189 } 190 191 sample(); 192 193 log.debug("Sampler end"); 194 onSamplerEnd(); 195 if (perfEventListener != null) { 196 perfEventListener.onSamplerEnd(this); 197 } 198 199 if (rampDownTime > 0) { 200 try { 201 Thread.sleep(rampDownTime); 202 } catch (InterruptedException e) { 203 e.printStackTrace(); 204 } 205 } 206 207 log.debug("Ramp down end"); 208 onRampDownEnd(); 209 if (perfEventListener != null) { 210 perfEventListener.onRampDownEnd(this); 211 } 212 } finally { 213 completionLatch.countDown(); 214 } 215 } 216 217 protected void sample() { 218 while (isRunning.get()) { 219 try { 220 Thread.sleep(interval); 221 } catch (InterruptedException e) { 222 e.printStackTrace(); 223 } 224 sampleData(); 225 sampleIndex++; 226 } 227 } 228 229 @Override 230 public abstract void sampleData(); 231 232 // Call back functions to customize behavior of thread. 233 protected void onRampUpStart() { 234 } 235 236 protected void onSamplerStart() { 237 } 238 239 protected void onSamplerEnd() { 240 } 241 242 protected void onRampDownEnd() { 243 } 244}