Skip to content

Commit

Permalink
Use AtomicInteger + mod instead of synchronizing threads in CountingS…
Browse files Browse the repository at this point in the history
…ampler. (openzipkin#857)
  • Loading branch information
anuraaga authored and adriancole committed Jan 21, 2019
1 parent cff6ac4 commit d4cbd86
Show file tree
Hide file tree
Showing 2 changed files with 24 additions and 7 deletions.
27 changes: 21 additions & 6 deletions brave/src/main/java/brave/sampler/CountingSampler.java
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,7 @@

import java.util.BitSet;
import java.util.Random;
import java.util.concurrent.atomic.AtomicInteger;

/**
* This sampler is appropriate for low-traffic instrumentation (ex servers that each receive <100K
Expand Down Expand Up @@ -29,28 +30,42 @@ public static Sampler create(final float rate) {
return new CountingSampler(rate);
}

private int i; // guarded by this
private final AtomicInteger counter;
private final BitSet sampleDecisions;

/** Fills a bitset with decisions according to the supplied rate. */
CountingSampler(float rate) {
this(rate, new Random());
}

/**
* Fills a bitset with decisions according to the supplied rate with the supplied {@link Random}.
*/
CountingSampler(float rate, Random random) {
counter = new AtomicInteger();
int outOf100 = (int) (rate * 100.0f);
this.sampleDecisions = randomBitSet(100, outOf100, new Random());
this.sampleDecisions = randomBitSet(100, outOf100, random);
}

/** loops over the pre-canned decisions, resetting to zero when it gets to the end. */
@Override
public synchronized boolean isSampled(long traceIdIgnored) {
boolean result = sampleDecisions.get(i++);
if (i == 100) i = 0;
return result;
public boolean isSampled(long traceIdIgnored) {
return sampleDecisions.get(mod(counter.getAndIncrement(), 100));
}

@Override
public String toString() {
return "CountingSampler()";
}

/**
* Returns a non-negative mod.
*/
static int mod(int dividend, int divisor) {
int result = dividend % divisor;
return result >= 0 ? result : divisor + result;
}

/**
* Reservoir sampling algorithm borrowed from Stack Overflow.
*
Expand Down
Original file line number Diff line number Diff line change
@@ -1,6 +1,7 @@
package brave.sampler;

import com.amazonaws.xray.strategy.sampling.reservoir.Reservoir;
import java.util.Random;
import java.util.concurrent.TimeUnit;
import org.openjdk.jmh.annotations.Benchmark;
import org.openjdk.jmh.annotations.BenchmarkMode;
Expand Down Expand Up @@ -90,7 +91,8 @@ public static class Args {
return SAMPLER_RATE.isSampled(args.traceId);
}

static final Sampler SAMPLER_RATE = CountingSampler.create(SAMPLE_RATE);
// Use fixed-seed Random so performance of runs can be compared.
static final Sampler SAMPLER_RATE = new CountingSampler(SAMPLE_RATE, new Random(1000));

@Benchmark public boolean sampler_rateLimited_1(Args args) {
return SAMPLER_RATE_LIMITED.isSampled(args.traceId);
Expand Down

0 comments on commit d4cbd86

Please sign in to comment.