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 test clients for benchmarking. #632

1 change: 0 additions & 1 deletion java/.cargo/config.toml
Original file line number Diff line number Diff line change
@@ -1,4 +1,3 @@
[env]
BABUSHKA_NAME = { value = "javababushka", force = true }
BABUSHKA_VERSION = "0.1.0"

7 changes: 3 additions & 4 deletions java/README.md
Original file line number Diff line number Diff line change
Expand Up @@ -6,11 +6,11 @@ language api to enhance performance and limit cpu cycles at scale.

## Organization

The Java client (javababushka) contains the following parts:
The Java client contains the following parts:

1. A Java client (lib folder): wrapper to rust-client.
2. An examples script: to sanity test javababushka and similar java-clients against a redis host.
3. A benchmark app: to performance benchmark test javababushka and similar java-clients against a redis host.
2. An examples script: to sanity test babushka and similar java-clients against a redis host.
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I couldn't find this script?

Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

And we don't want the examples folder to contain examples of other clients, only babushka

Copy link
Collaborator Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

It does not exist yet (as well as the client itself)
Updated in 3e0f70b.

3. A benchmark app: to performance benchmark test babushka and similar java-clients against a redis host.
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

A benchmark app: A dedicated benchmarking tool designed to evaluate and compare the performance of Babushka and other Java clients.

Copy link
Collaborator Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Updated in 3e0f70b


## Building

Expand Down Expand Up @@ -47,4 +47,3 @@ The following arguments are accepted:
* Connection Timeout:
* If you're unable to connect to redis, check that you are connecting to the correct host, port, and TLS configuration.
* Only server-side certificates are supported by the TLS configured redis.

4 changes: 2 additions & 2 deletions java/benchmarks/build.gradle
Original file line number Diff line number Diff line change
Expand Up @@ -29,10 +29,10 @@ java {

application {
// Define the main class for the application.
mainClass = 'javababushka.benchmarks.BenchmarkingApp'
mainClass = 'babushka.benchmarks.BenchmarkingApp'
}

tasks.withType(Test) {
tasks.withType(Test) {
testLogging {
exceptionFormat "full"
events "started", "skipped", "passed", "failed"
Expand Down
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
package javababushka.benchmarks;
package babushka.benchmarks;

import java.io.FileWriter;
import java.io.IOException;
Expand Down Expand Up @@ -30,7 +30,7 @@ public static void main(String[] args) {
// generate the help statement
if (line.hasOption("help")) {
HelpFormatter formatter = new HelpFormatter();
formatter.printHelp("javababushka", options);
formatter.printHelp("babushka", options);
return;
}

Expand All @@ -46,10 +46,6 @@ public static void main(String[] args) {
// run testClientSetGet on JEDIS sync client
System.out.println("Run JEDIS sync client");
break;
case JEDIS_ASYNC:
// run testClientSetGet on JEDIS pseudo-async client
System.out.println("Run JEDIS pseudo-async client");
break;
case LETTUCE:
// run testClientSetGet on LETTUCE sync client
System.out.println("Run LETTUCE sync client");
Expand Down Expand Up @@ -97,7 +93,7 @@ private static Options getOptions() {
.hasArg(true)
.desc(
"one of:"
+ " all|jedis|jedis_async|lettuce|lettuce_async|babushka_async|all_async|all_sync"
+ " all|jedis|lettuce|lettuce_async|babushka_async|all_async|all_sync"
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Commented on prev PR - make sure to rebase over the changes commited there

+ " [all]")
.build());
options.addOption(Option.builder("host").hasArg(true).desc("Hostname [localhost]").build());
Expand Down Expand Up @@ -150,13 +146,11 @@ private static RunConfiguration verifyOptions(CommandLine line) throws ParseExce
case ALL:
return Stream.of(
ClientName.JEDIS,
ClientName.JEDIS_ASYNC,
// ClientName.BABUSHKA_ASYNC,
ClientName.LETTUCE,
ClientName.LETTUCE_ASYNC);
case ALL_ASYNC:
return Stream.of(
ClientName.JEDIS_ASYNC,
// ClientName.BABUSHKA_ASYNC,
ClientName.LETTUCE_ASYNC);
case ALL_SYNC:
Expand Down Expand Up @@ -205,7 +199,6 @@ private static int[] parseIntListOption(String line) throws ParseException {

public enum ClientName {
JEDIS("Jedis"),
JEDIS_ASYNC("Jedis async"),
LETTUCE("Lettuce"),
LETTUCE_ASYNC("Lettuce async"),
BABUSHKA_ASYNC("Babushka async"),
Expand Down Expand Up @@ -249,7 +242,7 @@ public RunConfiguration() {
clients =
new ClientName[] {
// ClientName.BABUSHKA_ASYNC,
ClientName.JEDIS, ClientName.JEDIS_ASYNC, ClientName.LETTUCE, ClientName.LETTUCE_ASYNC
ClientName.JEDIS, ClientName.LETTUCE, ClientName.LETTUCE_ASYNC
};
host = "localhost";
port = 6379;
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,26 @@
package babushka.benchmarks.clients;

import java.util.concurrent.Future;
import java.util.concurrent.TimeUnit;

/** A Redis client with async capabilities */
public interface AsyncClient<T> extends Client {

long DEFAULT_TIMEOUT_MILLISECOND = 1000;

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

Future<String> asyncGet(String key);

default <T> T waitForResult(Future<T> future) {
return waitForResult(future, DEFAULT_TIMEOUT_MILLISECOND);
}

default <T> T waitForResult(Future<T> future, long timeout) {
try {
return future.get(timeout, TimeUnit.MILLISECONDS);
} catch (Exception ignored) {
return null;
}
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,12 @@
package babushka.benchmarks.clients;

import babushka.benchmarks.utils.ConnectionSettings;

/** A Redis client interface */
public interface Client {
void connectToRedis(ConnectionSettings connectionSettings);

default void closeConnection() {}

String getName();
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,8 @@
package babushka.benchmarks.clients;

/** A Redis client with sync capabilities */
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
@@ -0,0 +1,50 @@
package babushka.benchmarks.clients.babushka;

/*

public class JniNettyClient implements SyncClient, AsyncClient<Response> {
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Please remove it from this PR and add it when the java-babushka will be added

Copy link
Collaborator Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Removed in 3e0f70b.


private final Client testClient;
private String name = "JNI Netty";

public JniNettyClient(boolean async) {
name += async ? " async" : " sync";
testClient = new Client();
}

@Override
public String getName() {
return name;
}

@Override
public void closeConnection() {
testClient.closeConnection();
}

@Override
public void connectToRedis(ConnectionSettings connectionSettings) {
waitForResult(asyncConnectToRedis(connectionSettings));
}

@Override
public Future<Response> asyncSet(String key, String value) {
return testClient.asyncSet(key, value);
}

@Override
public Future<String> asyncGet(String key) {
return testClient.asyncGet(key);
}

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

@Override
public String get(String key) {
return testClient.get(key);
}
}
*/
Original file line number Diff line number Diff line change
@@ -0,0 +1,59 @@
package babushka.benchmarks.clients.jedis;

import babushka.benchmarks.clients.SyncClient;
import babushka.benchmarks.utils.ConnectionSettings;
import redis.clients.jedis.Jedis;
import redis.clients.jedis.JedisPool;

/** A Jedis client with sync capabilities. See: https://github.com/redis/jedis */
public class JedisClient implements SyncClient {

protected JedisPool pool;

@Override
public void closeConnection() {
// nothing to do
}

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

@Override
public void connectToRedis(ConnectionSettings connectionSettings) {
pool =
new JedisPool(connectionSettings.host, connectionSettings.port, connectionSettings.useSsl);
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

It looks like you're not testing Jedis in a cluster mode at all, redis cluster should be used with JedisCluster

Copy link
Collaborator Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Fixed in 3e0f70b.


// check if the pool is properly connected
try (Jedis jedis = pool.getResource()) {
assert jedis.isConnected() : "failed to connect to jedis";
}
}

public String info() {
try (Jedis jedis = pool.getResource()) {
return jedis.info();
}
}

public String info(String section) {
try (Jedis jedis = pool.getResource()) {
return jedis.info(section);
}
}

@Override
public void set(String key, String value) {
try (Jedis jedis = pool.getResource()) {
jedis.set(key, value);
}
}

@Override
public String get(String key) {
try (Jedis jedis = pool.getResource()) {
return jedis.get(key);
}
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,53 @@
package babushka.benchmarks.clients.lettuce;

import babushka.benchmarks.clients.AsyncClient;
import babushka.benchmarks.utils.ConnectionSettings;
import io.lettuce.core.RedisClient;
import io.lettuce.core.RedisFuture;
import io.lettuce.core.api.StatefulRedisConnection;
import io.lettuce.core.api.async.RedisAsyncCommands;
import java.time.Duration;

/** A Lettuce client with async capabilities see: https://lettuce.io/ */
public class LettuceAsyncClient implements AsyncClient<String> {
static final int ASYNC_OPERATION_TIMEOUT_SEC = 1;

private RedisClient client;
private RedisAsyncCommands asyncCommands;
private StatefulRedisConnection<String, String> connection;

@Override
public void connectToRedis(ConnectionSettings connectionSettings) {
client =
RedisClient.create(
String.format(
"%s://%s:%d",
connectionSettings.useSsl ? "rediss" : "redis",
connectionSettings.host,
connectionSettings.port));
connection = client.connect();
connection.setTimeout(Duration.ofSeconds(ASYNC_OPERATION_TIMEOUT_SEC));
asyncCommands = connection.async();
}

@Override
public RedisFuture<String> asyncSet(String key, String value) {
return asyncCommands.set(key, value);
}

@Override
public RedisFuture<String> asyncGet(String key) {
return asyncCommands.get(key);
}

@Override
public void closeConnection() {
connection.close();
client.shutdown();
}

@Override
public String getName() {
return "Lettuce Async";
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,54 @@
/*
* This Java source file was generated by the Gradle 'init' task.
*/
package babushka.benchmarks.clients.lettuce;

import babushka.benchmarks.utils.ConnectionSettings;
import io.lettuce.core.RedisFuture;
import io.lettuce.core.RedisURI;
import io.lettuce.core.cluster.RedisClusterClient;
import io.lettuce.core.cluster.api.StatefulRedisClusterConnection;
import io.lettuce.core.cluster.api.async.RedisAdvancedClusterAsyncCommands;
import java.time.Duration;

public class LettuceAsyncClusterClient extends LettuceAsyncClient {

private RedisClusterClient clusterClient;
private RedisAdvancedClusterAsyncCommands clusterAsyncCommands;
private StatefulRedisClusterConnection<String, String> clusterConnection;

@Override
public void connectToRedis(ConnectionSettings connectionSettings) {
Copy link
Collaborator

@barshaul barshaul Dec 11, 2023

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

@Yury-Fridlyand I think that the same as you did for Jedis, no need to have a separate file for LettuceClusterClient, you can use LettuceAsyncClient both for standalone and cluster

RedisURI uri =
RedisURI.builder()
.withHost(connectionSettings.host)
.withPort(connectionSettings.port)
.withSsl(connectionSettings.useSsl)
.build();
clusterClient = RedisClusterClient.create(uri);
clusterConnection = clusterClient.connect();
clusterConnection.setTimeout(Duration.ofSeconds(ASYNC_OPERATION_TIMEOUT_SEC));
clusterAsyncCommands = clusterConnection.async();
}

@Override
public RedisFuture<String> asyncSet(String key, String value) {
return clusterAsyncCommands.set(key, value);
}

@Override
public RedisFuture<String> asyncGet(String key) {
return clusterAsyncCommands.get(key);
}

@Override
public void closeConnection() {
clusterConnection.close();
clusterClient.shutdown();
}

@Override
public String getName() {
return "Lettuce Cluster Async";
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,16 @@
package babushka.benchmarks.utils;

/** Redis-client settings */
public class ConnectionSettings {
public final String host;
public final int port;
public final boolean useSsl;
public final boolean clusterMode;

public ConnectionSettings(String host, int port, boolean useSsl, boolean clusterMode) {
this.host = host;
this.port = port;
this.useSsl = useSsl;
this.clusterMode = clusterMode;
}
}
Loading