mirror of
https://github.com/nosqlbench/nosqlbench.git
synced 2025-02-03 11:20:39 -06:00
encapsulate update logic into token pool
This commit is contained in:
parent
1e409332a8
commit
0af587d28c
@ -80,7 +80,7 @@ public class HybridRateLimiter implements Startable, RateLimiter {
|
||||
|
||||
private final static Logger logger = LogManager.getLogger(HybridRateLimiter.class);
|
||||
|
||||
private volatile TokenFiller filler;
|
||||
//private volatile TokenFiller filler;
|
||||
private volatile long starttime;
|
||||
|
||||
// rate controls
|
||||
@ -150,8 +150,9 @@ public class HybridRateLimiter implements Startable, RateLimiter {
|
||||
}
|
||||
|
||||
this.rateSpec = updatingRateSpec;
|
||||
this.filler = (this.filler == null) ? new TokenFiller(rateSpec, activityDef) : filler.apply(rateSpec);
|
||||
this.tokens = this.filler.getTokenPool();
|
||||
this.tokens = (this.tokens == null) ? new TokenPool(rateSpec, activityDef) : this.tokens.apply(rateSpec);
|
||||
// this.filler = (this.filler == null) ? new TokenFiller(rateSpec, activityDef) : filler.apply(rateSpec);
|
||||
// this.tokens = this.filler.getTokenPool();
|
||||
|
||||
if (this.state == State.Idle && updatingRateSpec.isAutoStart()) {
|
||||
this.start();
|
||||
@ -177,7 +178,7 @@ public class HybridRateLimiter implements Startable, RateLimiter {
|
||||
case Idle:
|
||||
long nanos = getNanoClockTime();
|
||||
this.starttime = nanos;
|
||||
this.filler.start();
|
||||
this.tokens.start();
|
||||
state = State.Started;
|
||||
break;
|
||||
}
|
||||
@ -191,7 +192,7 @@ public class HybridRateLimiter implements Startable, RateLimiter {
|
||||
case Started:
|
||||
long accumulatedWaitSinceLastStart = cumulativeWaitTimeNanos.get();
|
||||
cumulativeWaitTimeNanos.set(0L);
|
||||
return this.filler.restart() + accumulatedWaitSinceLastStart;
|
||||
return this.tokens.restart() + accumulatedWaitSinceLastStart;
|
||||
default:
|
||||
return 0L;
|
||||
}
|
||||
@ -215,14 +216,14 @@ public class HybridRateLimiter implements Startable, RateLimiter {
|
||||
@Override
|
||||
public String toString() {
|
||||
StringBuilder sb = new StringBuilder(HybridRateLimiter.class.getSimpleName());
|
||||
if (this.getRateSpec()!=null) {
|
||||
if (this.getRateSpec() != null) {
|
||||
sb.append(" spec=").append(this.getRateSpec().toString());
|
||||
}
|
||||
if (this.state!=null) {
|
||||
if (this.state != null) {
|
||||
sb.append(" state=").append(this.state);
|
||||
}
|
||||
if (this.filler !=null) {
|
||||
sb.append(" filler=").append(this.filler.toString());
|
||||
if (this.tokens != null) {
|
||||
sb.append(" tokens=").append(this.tokens.toString());
|
||||
}
|
||||
return sb.toString();
|
||||
}
|
||||
@ -245,7 +246,7 @@ public class HybridRateLimiter implements Startable, RateLimiter {
|
||||
|
||||
@Override
|
||||
public Long getValue() {
|
||||
TokenPool pool = rl.filler.getTokenPool();
|
||||
TokenPool pool = rl.tokens;
|
||||
if (pool==null) {
|
||||
return 0L;
|
||||
}
|
||||
|
@ -48,18 +48,16 @@ public class TokenFiller implements Runnable {
|
||||
* in the JVM.
|
||||
*
|
||||
* @param rateSpec A {@link RateSpec}
|
||||
* @param def An {@link ActivityDef}
|
||||
* @param def An {@link ActivityDef}
|
||||
*/
|
||||
public TokenFiller(RateSpec rateSpec, ActivityDef def) {
|
||||
public TokenFiller(RateSpec rateSpec, TokenPool tokenPool, ActivityDef def) {
|
||||
this.rateSpec = rateSpec;
|
||||
this.tokenPool= new TokenPool(rateSpec);
|
||||
this.tokenPool.refill(rateSpec.getNanosPerOp());
|
||||
this.tokenPool = tokenPool;
|
||||
this.timer = ActivityMetrics.timer(def, "tokenfiller");
|
||||
}
|
||||
|
||||
public TokenFiller apply(RateSpec rateSpec) {
|
||||
this.rateSpec = rateSpec;
|
||||
this.tokenPool.apply(rateSpec);
|
||||
return this;
|
||||
}
|
||||
|
||||
@ -99,6 +97,8 @@ public class TokenFiller implements Runnable {
|
||||
}
|
||||
|
||||
public TokenFiller start() {
|
||||
this.tokenPool.refill(rateSpec.getNanosPerOp());
|
||||
|
||||
thread = new Thread(this);
|
||||
thread.setName(this.toString());
|
||||
thread.setPriority(Thread.MAX_PRIORITY);
|
||||
|
@ -17,8 +17,9 @@
|
||||
|
||||
package io.nosqlbench.engine.api.activityapi.ratelimits;
|
||||
|
||||
import org.apache.logging.log4j.Logger;
|
||||
import io.nosqlbench.engine.api.activityimpl.ActivityDef;
|
||||
import org.apache.logging.log4j.LogManager;
|
||||
import org.apache.logging.log4j.Logger;
|
||||
|
||||
import static io.nosqlbench.engine.api.util.Colors.*;
|
||||
|
||||
@ -57,10 +58,12 @@ public class TokenPool {
|
||||
private volatile long waitingPool;
|
||||
private RateSpec rateSpec;
|
||||
private long nanosPerOp;
|
||||
// private long debugTrigger=0L;
|
||||
// private long debugTrigger=0L;
|
||||
// private long debugRate=1000000000;
|
||||
private long blocks = 0L;
|
||||
|
||||
private TokenFiller filler;
|
||||
private final ActivityDef activityDef;
|
||||
|
||||
/**
|
||||
* This constructor tries to pick reasonable defaults for the token pool for
|
||||
@ -69,16 +72,11 @@ public class TokenPool {
|
||||
*
|
||||
* @param rateSpec a {@link RateSpec}
|
||||
*/
|
||||
public TokenPool(RateSpec rateSpec) {
|
||||
public TokenPool(RateSpec rateSpec, ActivityDef activityDef) {
|
||||
this.activityDef = activityDef;
|
||||
apply(rateSpec);
|
||||
logger.debug("initialized token pool: " + this.toString() + " for rate:" + rateSpec.toString());
|
||||
}
|
||||
|
||||
public TokenPool(long poolsize, double burstRatio) {
|
||||
this.maxActivePool = poolsize;
|
||||
this.burstRatio = burstRatio;
|
||||
this.maxOverActivePool = (long) (maxActivePool * burstRatio);
|
||||
this.burstPoolSize = maxOverActivePool - maxActivePool;
|
||||
// filler.start();
|
||||
}
|
||||
|
||||
/**
|
||||
@ -87,15 +85,17 @@ public class TokenPool {
|
||||
*
|
||||
* @param rateSpec The rate specifier.
|
||||
*/
|
||||
public synchronized void apply(RateSpec rateSpec) {
|
||||
this.rateSpec=rateSpec;
|
||||
public synchronized TokenPool apply(RateSpec rateSpec) {
|
||||
this.rateSpec = rateSpec;
|
||||
this.maxActivePool = Math.max((long) 1E6, (long) ((double) rateSpec.getNanosPerOp() * MIN_CONCURRENT_OPS));
|
||||
this.maxOverActivePool = (long) (maxActivePool * rateSpec.getBurstRatio());
|
||||
this.burstRatio = rateSpec.getBurstRatio();
|
||||
|
||||
this.burstPoolSize = maxOverActivePool - maxActivePool;
|
||||
this.nanosPerOp = rateSpec.getNanosPerOp();
|
||||
this.filler = (this.filler == null) ? new TokenFiller(rateSpec, this, activityDef) : filler.apply(rateSpec);
|
||||
notifyAll();
|
||||
return this;
|
||||
}
|
||||
|
||||
|
||||
@ -243,10 +243,14 @@ public class TokenPool {
|
||||
}
|
||||
|
||||
public synchronized long restart() {
|
||||
long wait=activePool+waitingPool;
|
||||
activePool=0L;
|
||||
waitingPool=0L;
|
||||
long wait = activePool + waitingPool;
|
||||
activePool = 0L;
|
||||
waitingPool = 0L;
|
||||
filler.restart();
|
||||
return wait;
|
||||
}
|
||||
|
||||
public void start() {
|
||||
filler.start();
|
||||
}
|
||||
}
|
||||
|
@ -17,30 +17,33 @@
|
||||
|
||||
package io.nosqlbench.engine.api.activityapi.ratelimits;
|
||||
|
||||
import org.junit.Ignore;
|
||||
import io.nosqlbench.engine.api.activityimpl.ActivityDef;
|
||||
import io.nosqlbench.engine.api.activityimpl.ParameterMap;
|
||||
import org.junit.Test;
|
||||
|
||||
import static org.assertj.core.api.Assertions.assertThat;
|
||||
|
||||
public class TokenPoolTest {
|
||||
|
||||
ActivityDef def = new ActivityDef(ParameterMap.parseOrException("alias=testing"));
|
||||
|
||||
@Test
|
||||
public void testBackfillFullRate() {
|
||||
TokenPool p = new TokenPool(100, 1.1);
|
||||
assertThat(p.refill(100L)).isEqualTo(100L);
|
||||
TokenPool p = new TokenPool(new RateSpec(10000000, 1.1), def);
|
||||
assertThat(p.refill(1000000L)).isEqualTo(1000000L);
|
||||
assertThat(p.getWaitPool()).isEqualTo(0L);
|
||||
assertThat(p.refill(100L)).isEqualTo(200);
|
||||
assertThat(p.refill(100L)).isEqualTo(1000100);
|
||||
assertThat(p.getWaitPool()).isEqualTo(90L);
|
||||
assertThat(p.refill(10L)).isEqualTo(210L);
|
||||
assertThat(p.getWaitPool()).isEqualTo(100L);
|
||||
assertThat(p.refill(10L)).isEqualTo(1000110L);
|
||||
assertThat(p.getWaitPool()).isEqualTo(99L);
|
||||
|
||||
assertThat(p.refill(10)).isEqualTo(220L);
|
||||
assertThat(p.refill(10)).isEqualTo(1000120L);
|
||||
assertThat(p.takeUpTo(100)).isEqualTo(100L);
|
||||
|
||||
}
|
||||
@Test
|
||||
public void testTakeRanges() {
|
||||
TokenPool p = new TokenPool(100, 10);
|
||||
TokenPool p = new TokenPool(new RateSpec(100, 10), def);
|
||||
p.refill(100);
|
||||
assertThat(p.takeUpTo(99)).isEqualTo(99L);
|
||||
assertThat(p.takeUpTo(10)).isEqualTo(1L);
|
||||
@ -51,7 +54,7 @@ public class TokenPoolTest {
|
||||
public void testChangedParameters() {
|
||||
|
||||
RateSpec s1 = new RateSpec(1000L, 1.10D);
|
||||
TokenPool p = new TokenPool(s1);
|
||||
TokenPool p = new TokenPool(s1, def);
|
||||
long r = p.refill(10000000);
|
||||
assertThat(r).isEqualTo(10000000L);
|
||||
assertThat(p.getWaitTime()).isEqualTo(10000000L);
|
||||
|
@ -37,7 +37,7 @@
|
||||
<jaxb.impl.version>2.4.0-b180830.0438</jaxb.impl.version>
|
||||
<jersey.media.version>2.29</jersey.media.version>
|
||||
<jersey.version>2.27</jersey.version>
|
||||
<jetty.version>9.4.25.v20191220</jetty.version>
|
||||
<jetty.version>9.4.35.v20201120</jetty.version>
|
||||
<jmh.version>1.22</jmh.version>
|
||||
<joda.time.version>2.9.9</joda.time.version>
|
||||
<junit.jupiter.version>5.3.2</junit.jupiter.version>
|
||||
|
Loading…
Reference in New Issue
Block a user