package org.gbif.occurrence.persistence.keygen;
import org.gbif.occurrence.common.config.OccHBaseConfiguration;
import java.io.IOException;
import java.util.List;
import java.util.UUID;
import java.util.concurrent.TimeUnit;
import java.util.concurrent.atomic.AtomicInteger;
import com.google.common.collect.ImmutableSet;
import com.google.common.collect.Lists;
import org.apache.hadoop.conf.Configuration;
import org.apache.hadoop.hbase.HBaseConfiguration;
import org.apache.hadoop.hbase.client.Connection;
import org.apache.hadoop.hbase.client.ConnectionFactory;
/**
* Note not a real JUnit test, but an extremely expensive performance test that should use the real cluster.
*/
public class HBaseLockingKeyServiceThroughputTest {
private static final OccHBaseConfiguration CFG = new OccHBaseConfiguration();
static {
CFG.setEnvironment("keygen_test");
}
private Connection connection = null;
private final HBaseLockingKeyService keyService;
private static final AtomicInteger keysGenerated = new AtomicInteger(0);
public HBaseLockingKeyServiceThroughputTest(int hbasePoolSize) throws IOException {
Configuration hBaseConfiguration = HBaseConfiguration.create();
hBaseConfiguration.set("hbase.hconnection.threads.max", Integer.toString(hbasePoolSize));
connection = ConnectionFactory.createConnection(hBaseConfiguration);
keyService = new HBaseLockingKeyService(CFG, connection);
}
public void testNoContention(int threadCount) throws InterruptedException {
// test generating ids as fast as possible in the ideal case of no waiting for contention (all ids are globally
// unique)
int genPerThread = 100000;
List<Thread> threads = Lists.newArrayList();
for (int i = 0; i < threadCount; i++) {
Thread thread = new Thread(new KeyGenerator(keyService, UUID.randomUUID(), genPerThread));
thread.start();
threads.add(thread);
}
Thread rateReporter = new Thread(new RateReporter(threadCount));
rateReporter.start();
for (Thread thread : threads) {
thread.join();
}
rateReporter.interrupt();
rateReporter.join();
}
private static class RateReporter implements Runnable {
private final int threadCount;
private RateReporter(int threadCount) {
this.threadCount = threadCount;
}
@Override
public void run() {
int periods = 0;
int runningAvg = 0;
int buildAverageAfter = 15;
int lastCount = 0;
boolean interrupted = false;
while (!interrupted) {
try {
TimeUnit.SECONDS.sleep(1);
} catch (InterruptedException e) {
interrupted = true;
}
int generated = keysGenerated.intValue() - lastCount;
if (periods > buildAverageAfter) {
if (runningAvg == 0) {
runningAvg = generated;
} else {
int netPeriods = periods - buildAverageAfter;
runningAvg = (netPeriods * runningAvg + generated) / (netPeriods + 1);
}
System.out.println("Key generation at [" + generated + " keys/s] for running avg of [" + runningAvg
+ " keys/s] and per thread [" + (runningAvg / threadCount)
+ " keys/sec] with id generation time of [" + (threadCount * 1000 / runningAvg)
+ " ms/id]");
} else {
System.out.println("Stats in [" + (buildAverageAfter - periods) + "] seconds.");
}
periods++;
lastCount = keysGenerated.intValue();
}
}
}
private static class KeyGenerator implements Runnable {
private final HBaseLockingKeyService keyService;
private final UUID datasetKey;
private final int genCount;
private KeyGenerator(HBaseLockingKeyService keyService, UUID datasetKey, int genCount) {
this.keyService = keyService;
this.datasetKey = datasetKey;
this.genCount = genCount;
}
@Override
public void run() {
for (int i = 0; i < genCount; i++) {
keyService.generateKey(ImmutableSet.of(String.valueOf(i)), datasetKey.toString());
keysGenerated.incrementAndGet();
}
}
}
public static void main(String[] args) throws InterruptedException, IOException {
int hbasePoolSize = 100;
int persistingThreads = 100;
if (args.length == 2) {
hbasePoolSize = Integer.valueOf(args[0]);
persistingThreads = Integer.valueOf(args[1]);
}
System.out
.println("Running test with hbasePool [" + hbasePoolSize + "] and persistingThreads [" + persistingThreads + "]");
HBaseLockingKeyServiceThroughputTest instance = new HBaseLockingKeyServiceThroughputTest(hbasePoolSize);
instance.testNoContention(persistingThreads);
}
}