package com.alibaba.doris.client.test;
import java.net.InetSocketAddress;
import java.util.concurrent.CountDownLatch;
import java.util.concurrent.ExecutorService;
import java.util.concurrent.Executors;
import java.util.concurrent.atomic.AtomicInteger;
import java.util.concurrent.atomic.AtomicLong;
import org.apache.commons.lang.math.RandomUtils;
import com.alibaba.doris.algorithm.vpm.VpmRouterAlgorithm;
import com.alibaba.doris.cli.CommandLineHandler;
import com.alibaba.doris.cli.Option;
import com.alibaba.doris.client.DataStore;
import com.alibaba.doris.client.DataStoreFactory;
import com.alibaba.doris.client.DataStoreFactoryImpl;
import com.alibaba.doris.client.net.Connection;
import com.alibaba.doris.client.net.ConnectionFactory;
import com.alibaba.doris.common.data.Key;
import com.alibaba.doris.common.data.KeyFactory;
/**
* @author ajun Email:jack.yuj@alibaba-inc.com
*/
public class PressureTestingTool extends CommandLineHandler {
/**
* @param args
*/
public static void main(String[] args) {
PressureTestingTool pressureTestingTool = new PressureTestingTool();
pressureTestingTool.handle(args);
System.exit(0);
}
public PressureTestingTool() {
options.add(new Option("-c", "config", "Location of the config file.", false, true));
options.add(new Option("-threads", "thread", "Setting the thread number for this test."));
options.add(new Option("-s", "start", "Setting the start position of key."));
options.add(new Option("-e", "end", "Setting the end position of key."));
options.add(new Option("-ns", "namespace", "Setting the namespace."));
options.add(new Option("-repeat", "repeat", "Setting the repeat times for each thread."));
options.add(new Option("-ip", "ip", "Setting the ipaddress for remote dataserver.", false, true));
options.add(new Option("-kp", "ip", "Setting the key prefix."));
options.add(new Option("-op", "op", "Setting the operation which we want to execute. 'get' 'put'", false, true));
options.add(new Option("-vl", "vl", "Setting the length of value.", false, true));
options.add(new Option("-ssf", "ssf", "Use single store factory.", false, true));
}
@Override
public void handleCommand() {
if (config != null) {
dataStoreFactory = new DataStoreFactoryImpl(config);
}
startGate = new CountDownLatch(1);
endGate = new CountDownLatch(threads);
ExecutorService threadFactory = Executors.newFixedThreadPool(threads);
for (int i = 0; i < threads; i++) {
if (op == null || (!"put".equals(op))) {
if (config == null) {
threadFactory.execute(new SimpleGetThread());
} else {
threadFactory.execute(new GetThread());
}
} else {
threadFactory.execute(new PutThread());
}
}
startGate.countDown();
PrintThread printer = new PrintThread();
new Thread(printer).start();
try {
endGate.await();
printer.setStop(true);
Thread.sleep(100);
} catch (InterruptedException e) {
e.printStackTrace();
}
printStatisticInfo();
System.out.println("Exit testing program.");
}
@Override
public void prepareParameters() {
threads = commandLine.getInt("-threads");
config = commandLine.getValue("-c");
start = commandLine.getInt("-s");
end = commandLine.getInt("-e");
namespace = commandLine.getValue("-ns");
repeat = commandLine.getInt("-repeat");
ip = commandLine.getValue("-ip");
kp = commandLine.getValue("-kp");
op = commandLine.getValue("-op");
vl = commandLine.getInt("-vl");
if ("true".equalsIgnoreCase(commandLine.getValue("-ssf"))) {
useSingleStoreFactory = true;
}
if (end == 0) {
end = 500000;
}
length = end - start;
}
private void printStatisticInfo() {
long time = timeCounter.get();
long count = countCounter.get();
if (count > 0) {
System.out.println("Time:" + time + " count:" + count + " error:" + errorCounter.get() + " avg:"
+ (time / count));
}
}
private class GetThread implements Runnable {
public void run() {
DataStoreFactory dsf = null;
if (useSingleStoreFactory) {
dsf = dataStoreFactory;
} else {
dsf = new DataStoreFactoryImpl(config);
}
DataStore dataStore = dsf.getDataStore(namespace);
Object value = null;
long start = 0;
int loops = repeat;
try {
startGate.await();
while (loops-- > 0) {
start = System.currentTimeMillis();
value = dataStore.get(kp + randomPosition());
timeCounter.addAndGet(System.currentTimeMillis() - start);
countCounter.incrementAndGet();
if (value == null) {
errorCounter.incrementAndGet();
}
}
endGate.countDown();
} catch (Exception e) {
e.printStackTrace();
}
}
}
private class SimpleGetThread implements Runnable {
public void run() {
ConnectionFactory factory = ConnectionFactory.getInstance();
String[] ips = ip.split(":");
InetSocketAddress address = new InetSocketAddress(ips[0], Integer.valueOf(ips[1]));
Connection connection = factory.getConnection(address);
connection.open();
Object value = null;
long start = 0;
int loops = repeat;
try {
startGate.await();
while (loops-- > 0) {
start = System.currentTimeMillis();
value = connection.get(getKey(kp + String.valueOf(randomPosition()))).get();
timeCounter.addAndGet(System.currentTimeMillis() - start);
countCounter.incrementAndGet();
if (value == null) {
errorCounter.incrementAndGet();
}
}
endGate.countDown();
} catch (Exception e) {
e.printStackTrace();
} finally {
connection.close();
}
}
private Key getKey(String key) {
return KeyFactory.createKey(Integer.valueOf(namespace), key, algorithm.getVirtualByKey(namespace + ":"
+ key));
}
}
private class PutThread implements Runnable {
public void run() {
DataStoreFactory dsf = null;
if (useSingleStoreFactory) {
dsf = dataStoreFactory;
} else {
dsf = new DataStoreFactoryImpl(config);
}
DataStore dataStore = dsf.getDataStore(namespace);
long start = 0;
int loops = repeat;
try {
startGate.await();
while (loops-- > 0) {
start = System.currentTimeMillis();
dataStore.put(kp + randomPosition(), getValue());
timeCounter.addAndGet(System.currentTimeMillis() - start);
countCounter.incrementAndGet();
}
endGate.countDown();
} catch (Exception e) {
e.printStackTrace();
}
}
private String getValue() {
if (null == value) {
StringBuilder sb = new StringBuilder(vl);
for (int i = 0; i < vl; i++) {
sb.append("V");
}
value = sb.toString();
}
return value;
}
private String value;
}
private class PrintThread implements Runnable {
public void run() {
while (!isStop) {
sleep();
this.printStatisticInfo();
}
}
private void sleep() {
try {
Thread.sleep(1000);
} catch (InterruptedException e) {
e.printStackTrace();
}
}
public void setStop(boolean isStop) {
this.isStop = isStop;
}
private void printStatisticInfo() {
long time = timeCounter.get();
long count = countCounter.get();
long timeExpired = time - prevTime;
long countInner = count - prevCount;
prevCount = count;
prevTime = time;
if (countInner > 0) {
if (count > 0) {
System.out.println("Total time:" + time + " Total count:" + count + " Time:" + timeExpired
+ " count:" + countInner + " error:" + errorCounter.get() + " avg:"
+ (timeExpired / countInner));
}
}
}
private long prevTime;
private long prevCount;
private volatile boolean isStop = false;
}
private int randomPosition() {
return start + RandomUtils.nextInt(length);
}
VpmRouterAlgorithm algorithm = new VpmRouterAlgorithm(1, 10000);
private int threads;
private int start;
private int end;
private int length;
private String namespace;
private int repeat;
private AtomicLong timeCounter = new AtomicLong();
private AtomicLong countCounter = new AtomicLong();
private AtomicInteger errorCounter = new AtomicInteger();
private CountDownLatch startGate;
private CountDownLatch endGate;
private String config;
private String ip;
private String kp;
private int vl;
private String op;
private boolean useSingleStoreFactory = false;
private DataStoreFactory dataStoreFactory;
}