Skip to content

Instantly share code, notes, and snippets.

@mrniko
Last active March 18, 2019 15:15
Show Gist options
  • Save mrniko/12e74d76c69ccff9935e262bceb9a054 to your computer and use it in GitHub Desktop.
Save mrniko/12e74d76c69ccff9935e262bceb9a054 to your computer and use it in GitHub Desktop.
public class PerfTester {
private static final String MASTER_HOST = "redis://127.0.0.1:63820";
private static final String READ_REPLICA_HOST = "redis://127.0.0.1:63800";
private static final int TEST_RUNS = 10;
private static final int RETRY_ATTEMPTS = 3;
private static final int RETRY_INTERVAL_MS = 1500;
private static final int CONNECT_TIMEOUT_MS = 10_000;
private static final int TIMEOUT_MS = 3000;
public static void main(String[] args) throws Exception {
PerfTester tester = new PerfTester();
tester.run();
}
void run() throws Exception {
// SingleServer
// RedissonClient client = createClient(Arrays.asList(MASTER_HOST));
// Replicated
RedissonClient client = createClient(Arrays.asList(MASTER_HOST, READ_REPLICA_HOST));
for (int i = 0; i < TEST_RUNS; i++) {
RedisWriter writer = new RedisWriter(new ComplexObjectFactory(), client);
long before = System.currentTimeMillis();
writer.run();
long time = System.currentTimeMillis() - before;
Vector<Long> durations = writer.getDurations();
LongSummaryStatistics stats = durations.stream().collect(Collectors.summarizingLong((x) -> x));
System.out.println("Took: " + time + " " + stats);
Thread.sleep(1000 * 10);
}
client.shutdown();
System.out.println("Done.");
}
RedissonClient createClient(List<String> hosts) {
Config config = new Config();
final boolean isReplicated = hosts.size() > 1;
if (isReplicated) {
String[] addresses = hosts.toArray(new String[hosts.size()]);
config
.useReplicatedServers()
.setReadMode(ReadMode.SLAVE)
.addNodeAddress(addresses)
.setRetryAttempts(RETRY_ATTEMPTS)
.setRetryInterval(RETRY_INTERVAL_MS)
.setConnectTimeout(CONNECT_TIMEOUT_MS)
.setTimeout(TIMEOUT_MS);
} else {
config
.useSingleServer()
.setAddress(hosts.get(0))
.setRetryAttempts(RETRY_ATTEMPTS)
.setRetryInterval(RETRY_INTERVAL_MS)
.setConnectTimeout(CONNECT_TIMEOUT_MS)
.setTimeout(TIMEOUT_MS);
}
config.setNettyThreads(16);
config.setCodec(new JsonJacksonCodec());
return Redisson.create(config);
}
}
class RedisWriter {
private static final int NUM_ITEMS_TO_WRITE = 10_000;
private static final int NUM_THREADS = 20;
private final Factory factory;
private final RedissonClient client;
private final Vector<Long> durations = new Vector<>(NUM_ITEMS_TO_WRITE);
RedisWriter(Factory factory, RedissonClient client) {
this.factory = factory;
this.client = client;
}
void run() {
ThreadPoolExecutor executor = (ThreadPoolExecutor) Executors.newFixedThreadPool(NUM_THREADS);
for(int i = 0; i < NUM_ITEMS_TO_WRITE; i++) {
executor.submit(() -> {
String key = "testing_" + UUID.randomUUID().toString();
Object o = factory.create();
long before = System.currentTimeMillis();
try {
client.getBucket(key).get();
client.getBucket(key).setAsync(o);
} catch (Exception e) {
e.printStackTrace();
}
long time = System.currentTimeMillis() - before;
durations.add(time);
});
}
try {
executor.shutdown();
while (!executor.awaitTermination(5, TimeUnit.SECONDS)) {
System.out.println("Awaiting completion of threads.");
}
} catch(InterruptedException e) {
System.err.println(e.getMessage());
}
}
public Vector<Long> getDurations() {
return durations;
}
}
interface Factory<T> {
T create();
}
class ComplexObjectFactory implements Factory<ComplexObject> {
private NestedObjectFactory factory = new NestedObjectFactory();
@Override
public ComplexObject create() {
return new ComplexObject(RandomUtils.randomStatus(), RandomUtils.randomLocalDateTime(), RandomUtils.randomInt(), factory.create());
}
}
class NestedObjectFactory implements Factory<NestedObject> {
@Override
public NestedObject create() {
return new NestedObject(RandomUtils.randomType(), RandomUtils.randomInt(), RandomUtils.randomFloat(), RandomUtils.randomFloat(), RandomUtils.randomFloat());
}
}
class ComplexObject {
private ObjectStatus status;
private LocalDateTime createdDate;
private String transactionId;
private NestedObject data;
public ComplexObject() {}
public ComplexObject(ObjectStatus status, LocalDateTime createdDate, String transactionId, NestedObject data) {
this.status = status;
this.createdDate = createdDate;
this.transactionId = transactionId;
this.data = data;
}
public ObjectStatus getStatus() {
return status;
}
public void setStatus(ObjectStatus status) {
this.status = status;
}
public LocalDateTime getCreatedDate() {
return createdDate;
}
public void setCreatedDate(LocalDateTime createdDate) {
this.createdDate = createdDate;
}
public String getTransactionId() {
return transactionId;
}
public void setTransactionId(String transactionId) {
this.transactionId = transactionId;
}
public NestedObject getData() {
return data;
}
public void setData(NestedObject data) {
this.data = data;
}
}
class NestedObject {
private ObjectType type;
private String code;
private Float one, two, three;
public NestedObject() {}
public NestedObject(ObjectType type, String code, Float one, Float two, Float three) {
this.type = type;
this.code = code;
this.one = one;
this.two = two;
this.three = three;
}
public ObjectType getType() {
return type;
}
public void setType(ObjectType type) {
this.type = type;
}
public String getCode() {
return code;
}
public void setCode(String code) {
this.code = code;
}
public Float getOne() {
return one;
}
public void setOne(Float one) {
this.one = one;
}
public Float getTwo() {
return two;
}
public void setTwo(Float two) {
this.two = two;
}
public Float getThree() {
return three;
}
public void setThree(Float three) {
this.three = three;
}
}
enum ObjectType {
A, B, C, D
}
enum ObjectStatus {
PRE_CERTIFIED, CERTIFIED
}
class RandomUtils {
private static final ThreadLocalRandom R = ThreadLocalRandom.current();
static LocalDateTime randomLocalDateTime() {
return LocalDateTime.of(
R.nextInt(0, 2020),
R.nextInt(1, 12),
R.nextInt(1, 28),
R.nextInt(0, 23),
R.nextInt(0, 59)
);
}
static String randomInt() {
return String.valueOf(R.nextInt());
}
static float randomFloat() {
return R.nextFloat();
}
static ObjectType randomType() {
float f = randomFloat();
if (f > 0.75) {
return ObjectType.A;
} else if (f > 0.5) {
return ObjectType.B;
} else if (f > 0.25) {
return ObjectType.C;
} else {
return ObjectType.D;
}
}
static ObjectStatus randomStatus() {
return (randomFloat() > 0.5)
? ObjectStatus.CERTIFIED
: ObjectStatus.PRE_CERTIFIED;
}
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment