Last active
March 18, 2019 15:15
-
-
Save mrniko/12e74d76c69ccff9935e262bceb9a054 to your computer and use it in GitHub Desktop.
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
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