Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Add sync and async clients both to tests. #12

Merged
merged 2 commits into from
Sep 25, 2023
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Original file line number Diff line number Diff line change
@@ -0,0 +1,16 @@
package javabushka.client;

import java.util.concurrent.Future;

public interface AsyncClient extends Client {

long DEFAULT_TIMEOUT = 1000;

Future<?> asyncSet(String key, String value);

Future<String> asyncGet(String key);

<T> T waitForResult(Future<T> future);

<T> T waitForResult(Future<T> future, long timeout);
}
Original file line number Diff line number Diff line change
Expand Up @@ -3,15 +3,14 @@
import java.io.FileWriter;
import java.io.IOException;
import java.util.Arrays;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.util.Optional;
import java.util.stream.Collectors;
import javabushka.client.jedis.JedisClient;
import javabushka.client.jedis.JedisPseudoAsyncClient;
import javabushka.client.lettuce.LettuceAsyncClient;
import javabushka.client.lettuce.LettuceClient;
import javabushka.client.utils.Benchmarking;
import javabushka.client.utils.ChosenAction;
import org.apache.commons.cli.CommandLine;
import org.apache.commons.cli.CommandLineParser;
import org.apache.commons.cli.DefaultParser;
Expand All @@ -37,26 +36,41 @@ public static void main(String[] args) {
System.err.println("Parsing failed. Reason: " + exp.getMessage());
}

try {
switch (runConfiguration.clients) {
for (ClientName client : runConfiguration.clients) {
switch (client) {
case ALL:
testJedisClientResourceSetGet(runConfiguration);
testLettuceClientResourceSetGet(runConfiguration);
testClientSetGet(new JedisClient(), runConfiguration);
testClientSetGet(new LettuceClient(), runConfiguration);
testAsyncClientSetGet(new JedisPseudoAsyncClient(), runConfiguration);
testAsyncClientSetGet(new LettuceAsyncClient(), runConfiguration);
System.out.println("Babushka not yet configured");
break;
case ALL_ASYNC:
testAsyncClientSetGet(new JedisPseudoAsyncClient(), runConfiguration);
testAsyncClientSetGet(new LettuceAsyncClient(), runConfiguration);
System.out.println("Babushka not yet configured");
break;
case ALL_SYNC:
testClientSetGet(new JedisClient(), runConfiguration);
testClientSetGet(new LettuceClient(), runConfiguration);
System.out.println("Babushka not yet configured");
break;
case JEDIS:
testJedisClientResourceSetGet(runConfiguration);
testClientSetGet(new JedisClient(), runConfiguration);
break;
case JEDIS_ASYNC:
testAsyncClientSetGet(new JedisPseudoAsyncClient(), runConfiguration);
break;
case LETTUCE:
testLettuceClientResourceSetGet(runConfiguration);
testClientSetGet(new LettuceClient(), runConfiguration);
break;
case LETTUCE_ASYNC:
testAsyncClientSetGet(new LettuceAsyncClient(), runConfiguration);
break;
case BABUSHKA:
System.out.println("Babushka not yet configured");
break;
}
} catch (IOException ioException) {
System.out.println("Error writing to results file");
ioException.printStackTrace();
}

if (runConfiguration.resultsFile.isPresent()) {
Expand Down Expand Up @@ -123,18 +137,11 @@ private static RunConfiguration verifyOptions(CommandLine line) throws ParseExce
}

if (line.hasOption("clients")) {
String clients = line.getOptionValue("clients");
if (ClientName.ALL.isEqual(clients)) {
runConfiguration.clients = ClientName.ALL;
} else if (ClientName.JEDIS.isEqual(clients)) {
runConfiguration.clients = ClientName.JEDIS;
} else if (ClientName.LETTUCE.isEqual(clients)) {
runConfiguration.clients = ClientName.LETTUCE;
} else if (ClientName.BABUSHKA.isEqual(clients)) {
runConfiguration.clients = ClientName.BABUSHKA;
} else {
throw new ParseException("Invalid clients option: all|jedis|lettuce|babushka");
}
String[] clients = line.getOptionValue("clients").split(",");
runConfiguration.clients =
Arrays.stream(clients)
.map(c -> Enum.valueOf(ClientName.class, c.toUpperCase()))
.toArray(ClientName[]::new);
}

if (line.hasOption("host")) {
Expand All @@ -152,66 +159,27 @@ private static RunConfiguration verifyOptions(CommandLine line) throws ParseExce
return runConfiguration;
}

private static void testJedisClientResourceSetGet(RunConfiguration runConfiguration)
throws IOException {
JedisClient jedisClient = new JedisClient();
jedisClient.connectToRedis(runConfiguration.host, runConfiguration.port);

int iterations = 100000;
String value = "my-value";

if (runConfiguration.resultsFile.isPresent()) {
runConfiguration.resultsFile.get().write("JEDIS client Benchmarking: ");
} else {
System.out.println("JEDIS client Benchmarking: ");
}

Map<ChosenAction, Benchmarking.Operation> actions = new HashMap<>();
actions.put(ChosenAction.GET_EXISTING, () -> jedisClient.get(Benchmarking.generateKeySet()));
actions.put(
ChosenAction.GET_NON_EXISTING, () -> jedisClient.get(Benchmarking.generateKeyGet()));
actions.put(ChosenAction.SET, () -> jedisClient.set(Benchmarking.generateKeySet(), value));

Benchmarking.printResults(
Benchmarking.calculateResults(Benchmarking.getLatencies(iterations, actions)),
runConfiguration.resultsFile);
private static void testClientSetGet(Client client, RunConfiguration runConfiguration) {
System.out.printf("%n =====> %s <===== %n%n", client.getName());
Benchmarking.printResults(Benchmarking.measurePerformance(client, runConfiguration, false));
System.out.println();
}

private static LettuceAsyncClient initializeLettuceClient() {
LettuceAsyncClient lettuceClient = new LettuceAsyncClient();
lettuceClient.connectToRedis();
return lettuceClient;
}

private static void testLettuceClientResourceSetGet(RunConfiguration runConfiguration)
throws IOException {
LettuceAsyncClient lettuceClient = initializeLettuceClient();

int iterations = 100000;
String value = "my-value";

if (runConfiguration.resultsFile.isPresent()) {
runConfiguration.resultsFile.get().write("LETTUCE client Benchmarking: ");
} else {
System.out.println("LETTUCE client Benchmarking: ");
}

HashMap<ChosenAction, Benchmarking.Operation> actions = new HashMap<>();
actions.put(ChosenAction.GET_EXISTING, () -> lettuceClient.get(Benchmarking.generateKeySet()));
actions.put(
ChosenAction.GET_NON_EXISTING, () -> lettuceClient.get(Benchmarking.generateKeyGet()));
actions.put(ChosenAction.SET, () -> lettuceClient.set(Benchmarking.generateKeySet(), value));

Benchmarking.printResults(
Benchmarking.calculateResults(Benchmarking.getLatencies(iterations, actions)),
runConfiguration.resultsFile);
private static void testAsyncClientSetGet(AsyncClient client, RunConfiguration runConfiguration) {
System.out.printf("%n =====> %s <===== %n%n", client.getName());
Benchmarking.printResults(Benchmarking.measurePerformance(client, runConfiguration, true));
System.out.println();
}

public enum ClientName {
JEDIS("Jedis"),
JEDIS_ASYNC("Jedis async"),
LETTUCE("Lettuce"),
LETTUCE_ASYNC("Lettuce async"),
BABUSHKA("Babushka"),
ALL("All");
ALL("All"),
ALL_SYNC("All sync"),
ALL_ASYNC("All async");

private String name;

Expand All @@ -233,7 +201,7 @@ public static class RunConfiguration {
public String configuration;
public Optional<FileWriter> resultsFile;
public List<Integer> concurrentTasks;
public ClientName clients;
public ClientName[] clients;
public String host;
public int port;
public int clientCount;
Expand All @@ -243,11 +211,11 @@ public RunConfiguration() {
configuration = "Release";
resultsFile = Optional.empty();
concurrentTasks = List.of(1, 10, 100);
clients = ClientName.ALL;
clients = new ClientName[] {ClientName.ALL};
host = "localhost";
port = 6379;
clientCount = 1;
tls = true;
tls = false;
}
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,13 @@
package javabushka.client;

import javabushka.client.utils.ConnectionSettings;

public interface Client {
void connectToRedis();

void connectToRedis(ConnectionSettings connectionSettings);

default void closeConnection() {}

String getName();
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,7 @@
package javabushka.client;

public interface SyncClient extends Client {
void set(String key, String value);

String get(String key);
}
Original file line number Diff line number Diff line change
Expand Up @@ -3,27 +3,46 @@
*/
package javabushka.client.jedis;

import javabushka.client.SyncClient;
import javabushka.client.utils.ConnectionSettings;
import redis.clients.jedis.Jedis;
import redis.clients.jedis.JedisPool;

public class JedisClient {
public class JedisClient implements SyncClient {

public static final String DEFAULT_HOST = "localhost";
public static final int DEFAULT_PORT = 6379;

Jedis jedisResource;
protected Jedis jedisResource;

public boolean someLibraryMethod() {
return true;
}

public void connectToRedis(String host, int port) {
JedisPool pool = new JedisPool(host, port);
@Override
public void connectToRedis() {
JedisPool pool = new JedisPool(DEFAULT_HOST, DEFAULT_PORT);
jedisResource = pool.getResource();
}

public void connectToRedis() {
connectToRedis(DEFAULT_HOST, DEFAULT_PORT);
@Override
public void closeConnection() {
try {
jedisResource.close();
} catch (Exception ignored) {
}
}

@Override
public String getName() {
return "Jedis";
}

@Override
public void connectToRedis(ConnectionSettings connectionSettings) {
jedisResource =
new Jedis(connectionSettings.host, connectionSettings.port, connectionSettings.useSsl);
jedisResource.connect();
}

public String info() {
Expand All @@ -34,10 +53,12 @@ public String info(String section) {
return jedisResource.info(section);
}

@Override
public void set(String key, String value) {
jedisResource.set(key, value);
}

@Override
public String get(String key) {
return jedisResource.get(key);
}
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,39 @@
package javabushka.client.jedis;

import java.util.concurrent.CompletableFuture;
import java.util.concurrent.Future;
import java.util.concurrent.TimeUnit;
import javabushka.client.AsyncClient;

// Jedis doesn't provide async API
// https:/redis/jedis/issues/241
public class JedisPseudoAsyncClient extends JedisClient implements AsyncClient {
@Override
public Future<?> asyncSet(String key, String value) {
return CompletableFuture.runAsync(() -> super.set(key, value));
}

@Override
public Future<String> asyncGet(String key) {
return CompletableFuture.supplyAsync(() -> super.get(key));
}

@Override
public <T> T waitForResult(Future<T> future) {
return waitForResult(future, DEFAULT_TIMEOUT);
}

@Override
public <T> T waitForResult(Future<T> future, long timeout) {
try {
return future.get(timeout, TimeUnit.MILLISECONDS);
} catch (Exception ignored) {
return null;
}
}

@Override
public String getName() {
return "Jedis pseudo-async";
}
}
Loading
Loading