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

Java client jni netty #32

Merged
merged 50 commits into from
Nov 22, 2023
Merged
Show file tree
Hide file tree
Changes from 46 commits
Commits
Show all changes
50 commits
Select commit Hold shift + click to select a range
035ef20
Add Java-client benchmarking app
acarbonetto Oct 10, 2023
0883985
spotless apply
acarbonetto Oct 10, 2023
d15ade1
Update on command line options
acarbonetto Oct 10, 2023
e3634ba
Update README
acarbonetto Oct 10, 2023
500a043
Spotless apply:
acarbonetto Oct 10, 2023
0bf1678
Update README example
acarbonetto Oct 11, 2023
12efc63
update commandline defaults for review comments
acarbonetto Oct 11, 2023
951aa8b
Remove TLS flag argument from option
acarbonetto Oct 11, 2023
adc0bb6
Add lettuce clients for benchmarking
acarbonetto Oct 10, 2023
9fc9022
Spotless apply
acarbonetto Oct 10, 2023
111fc26
Add Jedis clients
acarbonetto Oct 10, 2023
9236e9a
Add to app
acarbonetto Oct 10, 2023
49654c3
Add for-loop for data size list
acarbonetto Oct 10, 2023
b3284c1
Add TPS for all async items
acarbonetto Oct 11, 2023
8f1dfa5
spotless apply
acarbonetto Oct 11, 2023
7f690cf
Fix TPS calculations
acarbonetto Oct 11, 2023
d00a655
Accept TLS as a flag
acarbonetto Oct 11, 2023
b5e9a33
Merge branch 'java-client/add_benchmark_app' into java-client/add_jed…
acarbonetto Oct 11, 2023
3cee673
Merge branch 'java-client/add_jedis_client' into java-client/add_tps
acarbonetto Oct 11, 2023
8dcfec0
Start threads; then wait for results
acarbonetto Oct 12, 2023
a615f8a
Add java-jni client
acarbonetto Oct 18, 2023
73c448f
Handle Exceptions from client; add JniSyncClient fixes
acarbonetto Oct 19, 2023
79459f5
Clean up latency and add error checking
acarbonetto Oct 20, 2023
917dd0e
Merge remote-tracking branch 'origin/java_benchmarks' into java-clien…
Yury-Fridlyand Oct 24, 2023
9e62324
Minor fixes.
Yury-Fridlyand Oct 24, 2023
11a78a3
Fix result printing.
Yury-Fridlyand Oct 25, 2023
a2c2670
Add TPS.
Yury-Fridlyand Oct 25, 2023
4b9f8de
Remove duplicates. Reorganize and fix imports.
Yury-Fridlyand Oct 25, 2023
d6b72ac
Int ctor fix.
Yury-Fridlyand Oct 26, 2023
58f7b58
Iteration 1.
Yury-Fridlyand Oct 31, 2023
d145bdf
Iteration 2: connected!
Yury-Fridlyand Oct 31, 2023
0b03dc5
Iteration 3: `get` and `set`.
Yury-Fridlyand Nov 1, 2023
a3075d5
Iteration 4: benchmark.
Yury-Fridlyand Nov 1, 2023
5f10964
Iteration 5: some fixes.
Yury-Fridlyand Nov 2, 2023
e3f7596
Change number of threads in Benchmarking threadpool
jonathanl-bq Nov 2, 2023
49c9119
Revert "Change number of threads in Benchmarking threadpool"
jonathanl-bq Nov 2, 2023
dd7413b
Add more flushing rules and UT.
Yury-Fridlyand Nov 3, 2023
a70c907
Client clean up.
Yury-Fridlyand Nov 16, 2023
fbea007
Client optimizations. (#37)
Yury-Fridlyand Nov 16, 2023
bb9097b
Merge remote-tracking branch 'origin/java_benchmarks' into java-clien…
Yury-Fridlyand Nov 16, 2023
2f8f93a
Address PR feedback.
Yury-Fridlyand Nov 16, 2023
f0f0e79
Rename
Yury-Fridlyand Nov 17, 2023
06ca6b4
Rename2
Yury-Fridlyand Nov 17, 2023
33a09c0
Fix CI
Yury-Fridlyand Nov 17, 2023
444a28c
More fixes.
Yury-Fridlyand Nov 17, 2023
e11a0ee
Some changes.
Yury-Fridlyand Nov 17, 2023
29ba2a3
add null check
Yury-Fridlyand Nov 20, 2023
16a8680
autoflush
Yury-Fridlyand Nov 20, 2023
3f47ba2
Apply suggestions from code review
Yury-Fridlyand Nov 22, 2023
61baa41
minor changes
Yury-Fridlyand Nov 22, 2023
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
4 changes: 1 addition & 3 deletions .github/workflows/java.yml
Original file line number Diff line number Diff line change
Expand Up @@ -41,12 +41,10 @@ jobs:
distribution: "temurin"
java-version: ${{ matrix.java }}

- name: Install and run protoc (protobuf)
- name: Install protoc (protobuf)
run: |
sudo apt update
sudo apt install -y protobuf-compiler
mkdir -p java/client/src/main/java/org/babushka/javababushka/generated
protoc -Iprotobuf=babushka-core/src/protobuf/ --java_out=java/client/src/main/java/org/babushka/javababushka/generated babushka-core/src/protobuf/*.proto
- name: Build rust part
working-directory: java
Expand Down
2 changes: 2 additions & 0 deletions benchmarks/utilities/csv_exporter.py
100644 → 100755
Original file line number Diff line number Diff line change
@@ -1,3 +1,5 @@
#!/bin/python3

import csv
import json
import os
Expand Down
2 changes: 2 additions & 0 deletions java/Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -15,6 +15,8 @@ babushka = { path = "../babushka-core" }
tokio = { version = "^1", features = ["rt", "macros", "rt-multi-thread", "time"] }
logger_core = {path = "../logger_core"}
tracing-subscriber = "0.3.16"
jni = "0.21.1"
log = "0.4.20"
acarbonetto marked this conversation as resolved.
Show resolved Hide resolved

[profile.release]
lto = true
Expand Down
20 changes: 14 additions & 6 deletions java/benchmarks/build.gradle
Original file line number Diff line number Diff line change
@@ -1,6 +1,7 @@
plugins {
// Apply the application plugin to add support for building a CLI application in Java.
id 'application'
id 'io.freefair.lombok'
}

repositories {
Expand All @@ -9,6 +10,8 @@ repositories {
}

dependencies {
implementation project(':client')

// Use JUnit test framework.
testImplementation 'org.junit.jupiter:junit-jupiter:5.9.2'

Expand All @@ -20,6 +23,9 @@ dependencies {
implementation group: 'org.apache.commons', name: 'commons-lang3', version: '3.13.0'
implementation group: 'com.google.code.gson', name: 'gson', version: '2.10.1'

//testImplementation group: 'org.slf4j', name: 'slf4j-reload4j', version: '2.0.9'
//testImplementation group: 'org.slf4j', name: 'slf4j-api', version: '2.0.9'
acarbonetto marked this conversation as resolved.
Show resolved Hide resolved

compileOnly 'org.projectlombok:lombok:1.18.30'
annotationProcessor 'org.projectlombok:lombok:1.18.30'
}
Expand All @@ -34,12 +40,14 @@ java {
application {
// Define the main class for the application.
mainClass = 'javababushka.benchmarks.BenchmarkingApp'
applicationDefaultJvmArgs += "-Djava.library.path=${projectDir}/../target/release:${projectDir}/../target/debug"
}

tasks.withType(Test) {
testLogging {
exceptionFormat "full"
events "started", "skipped", "passed", "failed"
showStandardStreams true
}
tasks.withType(Test) {
testLogging {
exceptionFormat "full"
events "started", "skipped", "passed", "failed"
showStandardStreams true
}
jvmArgs "-Djava.library.path=${projectDir}/../target/release:${projectDir}/../target/debug"
}

This file was deleted.

Original file line number Diff line number Diff line change
Expand Up @@ -5,11 +5,12 @@
import java.util.Arrays;
import java.util.Optional;
import java.util.stream.Stream;
import javababushka.benchmarks.jedis.JedisClient;
import javababushka.benchmarks.jedis.JedisPseudoAsyncClient;
import javababushka.benchmarks.lettuce.LettuceAsyncClient;
import javababushka.benchmarks.lettuce.LettuceAsyncClusterClient;
import javababushka.benchmarks.lettuce.LettuceClient;
import javababushka.benchmarks.clients.babushka.JniNettyClient;
import javababushka.benchmarks.clients.jedis.JedisClient;
import javababushka.benchmarks.clients.jedis.JedisPseudoAsyncClient;
import javababushka.benchmarks.clients.lettuce.LettuceAsyncClient;
import javababushka.benchmarks.clients.lettuce.LettuceAsyncClusterClient;
import javababushka.benchmarks.clients.lettuce.LettuceClient;
import org.apache.commons.cli.CommandLine;
import org.apache.commons.cli.CommandLineParser;
import org.apache.commons.cli.DefaultParser;
Expand Down Expand Up @@ -48,9 +49,11 @@ public static void main(String[] args) {
for (ClientName client : runConfiguration.clients) {
switch (client) {
case JEDIS:
// run testClientSetGet on JEDIS sync client
testClientSetGet(JedisClient::new, runConfiguration, false);
break;
case JEDIS_ASYNC:
// run testClientSetGet on JEDIS pseudo-async client
testClientSetGet(JedisPseudoAsyncClient::new, runConfiguration, true);
break;
case LETTUCE:
Expand All @@ -63,8 +66,11 @@ public static void main(String[] args) {
testClientSetGet(LettuceAsyncClient::new, runConfiguration, true);
}
break;
case BABUSHKA:
testClientSetGet(() -> new JniNettyClient(false), runConfiguration, false);
break;
case BABUSHKA_ASYNC:
System.out.println("Babushka async not yet configured");
testClientSetGet(() -> new JniNettyClient(true), runConfiguration, true);
break;
}
}
Expand Down Expand Up @@ -93,8 +99,8 @@ private static Options getOptions() {
Option.builder("clients")
.hasArg(true)
.desc(
"one of: all|jedis|jedis_async|lettuce|lettuce_async"
+ "|babushka_async|all_async|all_sync [all]")
"one of: all|jedis|jedis_async|lettuce|lettuce_async|"
+ "babushka|babushka_async|all_async|all_sync")
.build());
options.addOption(Option.builder("host").hasArg(true).desc("Hostname [localhost]").build());
options.addOption(Option.builder("port").hasArg(true).desc("Port number [6379]").build());
Expand Down Expand Up @@ -149,6 +155,7 @@ private static RunConfiguration verifyOptions(CommandLine line) throws ParseExce
return Stream.of(
ClientName.JEDIS,
ClientName.JEDIS_ASYNC,
ClientName.BABUSHKA,
ClientName.BABUSHKA_ASYNC,
ClientName.LETTUCE,
ClientName.LETTUCE_ASYNC);
Expand All @@ -158,7 +165,7 @@ private static RunConfiguration verifyOptions(CommandLine line) throws ParseExce
ClientName.BABUSHKA_ASYNC,
ClientName.LETTUCE_ASYNC);
case ALL_SYNC:
return Stream.of(ClientName.JEDIS, ClientName.LETTUCE);
return Stream.of(ClientName.JEDIS, ClientName.LETTUCE, ClientName.BABUSHKA);
default:
return Stream.of(e);
}
Expand Down Expand Up @@ -210,6 +217,7 @@ public enum ClientName {
LETTUCE("Lettuce"),
LETTUCE_ASYNC("Lettuce async"),
BABUSHKA_ASYNC("Babushka async"),
BABUSHKA("Babushka"),
ALL("All"),
ALL_SYNC("All sync"),
ALL_ASYNC("All async");
Expand All @@ -232,9 +240,9 @@ public boolean isEqual(String other) {

public static class RunConfiguration {
public String configuration;
public Optional<String> resultsFile;
public int[] dataSize;
public int[] concurrentTasks;
public Optional<String> resultsFile;
public ClientName[] clients;
public String host;
public int port;
Expand All @@ -251,7 +259,10 @@ public RunConfiguration() {
clients =
new ClientName[] {
// ClientName.BABUSHKA_ASYNC,
ClientName.LETTUCE_ASYNC
// ClientName.JEDIS, ClientName.JEDIS_ASYNC, ClientName.LETTUCE,
// ClientName.LETTUCE_ASYNC
ClientName.BABUSHKA_ASYNC,
ClientName.BABUSHKA // , ClientName.LETTUCE, ClientName.LETTUCE_ASYNC
};
host = "localhost";
port = 6379;
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,29 @@
package javababushka.benchmarks.clients;

import java.util.concurrent.Future;
import java.util.concurrent.TimeUnit;
import javababushka.benchmarks.utils.ConnectionSettings;

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

long DEFAULT_TIMEOUT_MILLISECOND = 1000;

Future<T> asyncConnectToRedis(ConnectionSettings connectionSettings);

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;

Choose a reason for hiding this comment

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

TODO: we should handle exceptions and track number of failed calls

}
}
}
Original file line number Diff line number Diff line change
@@ -1,7 +1,8 @@
package javababushka.benchmarks;
package javababushka.benchmarks.clients;

import javababushka.benchmarks.utils.ConnectionSettings;

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

Expand Down
Original file line number Diff line number Diff line change
@@ -1,5 +1,6 @@
package javababushka.benchmarks;
package javababushka.benchmarks.clients;

/** A Redis client with sync capabilities */
public interface SyncClient extends Client {
void set(String key, String value);

Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,69 @@
package javababushka.benchmarks.clients.babushka;

import static response.ResponseOuterClass.Response;

import java.util.concurrent.Future;
import javababushka.Client;
import javababushka.benchmarks.clients.AsyncClient;
import javababushka.benchmarks.clients.SyncClient;
import javababushka.benchmarks.utils.ConnectionSettings;

public class JniNettyClient implements SyncClient, AsyncClient<Response> {

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

public JniNettyClient(boolean async) {
name += async ? " async" : " sync";

Choose a reason for hiding this comment

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

probably don't need this

Copy link
Author

Choose a reason for hiding this comment

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

I use it only to distinguish clients in benchmarking.

testClient = new Client();

Choose a reason for hiding this comment

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

why test?

Copy link
Author

Choose a reason for hiding this comment

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

benchmarking is a kind of a test

}

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

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

@Override
public void connectToRedis() {
connectToRedis(new ConnectionSettings("localhost", 6379, false, false));
}

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

@Override
public Future<Response> asyncConnectToRedis(ConnectionSettings connectionSettings) {
return testClient.asyncConnectToRedis(
connectionSettings.host,
connectionSettings.port,
connectionSettings.useSsl,
connectionSettings.clusterMode);
}

@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
@@ -1,24 +1,18 @@
/*
* This Java source file was generated by the Gradle 'init' task.
*/
package javababushka.benchmarks.jedis;
package javababushka.benchmarks.clients.jedis;

import javababushka.benchmarks.SyncClient;
import javababushka.benchmarks.clients.SyncClient;
import javababushka.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 {
Yury-Fridlyand marked this conversation as resolved.
Show resolved Hide resolved

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

protected Jedis jedisResource;

public boolean someLibraryMethod() {
return true;
}

@Override
public void connectToRedis() {
JedisPool pool = new JedisPool(DEFAULT_HOST, DEFAULT_PORT);
Expand All @@ -43,6 +37,9 @@ public void connectToRedis(ConnectionSettings connectionSettings) {
jedisResource =
new Jedis(connectionSettings.host, connectionSettings.port, connectionSettings.useSsl);
jedisResource.connect();
if (!jedisResource.isConnected()) {
throw new RuntimeException("failed to connect to jedis");
}
}

public String info() {
Expand Down
Loading
Loading