Skip to content

Commit

Permalink
Add JNI FFI sync client to benchmarking.
Browse files Browse the repository at this point in the history
Signed-off-by: Yury-Fridlyand <[email protected]>
  • Loading branch information
Yury-Fridlyand committed Oct 26, 2023
1 parent b00a205 commit 9324ba7
Show file tree
Hide file tree
Showing 8 changed files with 544 additions and 15 deletions.
3 changes: 3 additions & 0 deletions java/Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -15,6 +15,9 @@ 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"
env_logger = "0.10.0"
log = "0.4.20"

[profile.release]
lto = true
Expand Down
2 changes: 2 additions & 0 deletions java/benchmarks/build.gradle
Original file line number Diff line number Diff line change
Expand Up @@ -34,6 +34,8 @@ java {
application {
// Define the main class for the application.
mainClass = 'javababushka.benchmarks.BenchmarkingApp'
// mainClass = 'javababushka.benchmarks.babushka.Jni'
applicationDefaultJvmArgs += "-Djava.library.path=${projectDir}/../target/debug"
}

tasks.withType(Test) {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,7 @@
import java.util.Arrays;
import java.util.Optional;
import java.util.stream.Stream;
import javababushka.benchmarks.babushka.JniFfi;
import javababushka.benchmarks.jedis.JedisClient;
import javababushka.benchmarks.jedis.JedisPseudoAsyncClient;
import javababushka.benchmarks.lettuce.LettuceAsyncClient;
Expand Down Expand Up @@ -46,6 +47,9 @@ public static void main(String[] args) {

for (ClientName client : runConfiguration.clients) {
switch (client) {
case JNI_FFI:
testClientSetGet(JniFfi::new, runConfiguration, false);
break;
case JEDIS:
testClientSetGet(JedisClient::new, runConfiguration, false);
break;
Expand Down Expand Up @@ -197,6 +201,7 @@ public enum ClientName {
LETTUCE_ASYNC("Lettuce async"),
BABUSHKA("Babushka"),
BABUSHKA_ASYNC("Babushka async"),
JNI_FFI("JNI FFI"),
ALL("All"),
ALL_SYNC("All sync"),
ALL_ASYNC("All async");
Expand Down Expand Up @@ -232,12 +237,12 @@ public static class RunConfiguration {
public RunConfiguration() {
configuration = "Release";
resultsFile = Optional.empty();
dataSize = new int[] {100, 4000};
concurrentTasks = new int[] {100, 1000};
dataSize = new int[] {20};
concurrentTasks = new int[] {10, 100};
clients =
new ClientName[] {
// ClientName.BABUSHKA_ASYNC,
ClientName.JEDIS, ClientName.JEDIS_ASYNC, ClientName.LETTUCE, ClientName.LETTUCE_ASYNC
ClientName.JEDIS, ClientName.LETTUCE, ClientName.JNI_FFI
};
host = "localhost";
port = 6379;
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,132 @@
package javababushka.benchmarks.babushka;

import java.nio.file.Paths;
import lombok.Builder;

public class Jni {
static {
System.setProperty(
"java.library.path",
Paths.get(System.getProperty("user.dir"), "target", "debug").toString());
System.loadLibrary("javababushka");
}

public static native long init_client(int a);

public static native BabushkaResult test(long ptr, String address);

public static native BabushkaResult connect(long ptr, String address);

public static native BabushkaResult set(long ptr, String name, String value);

public static native BabushkaResult get(long ptr, String name);

public static native BabushkaResult from_str(String str);

public static native BabushkaResult from_number(long num);

public static native BabushkaResult from_ok();

public static native BabushkaResult nnew(String str, int resultType, String string, long number);

public static enum ResultType {
STR, // * const c_char
NUM, // i64
NIL,
DATA, // Vec<u8>
BULK, // Vec<Value>
OK,
ERR;

public static ResultType of(int ordinal) {
switch (ordinal) {
case 0:
return STR;
case 1:
return NUM;
case 2:
return NIL;
case 3:
return DATA;
case 4:
return BULK;
case 5:
return OK;
default:
return ERR;
}
}
}

@Builder
public static class BabushkaResult {
public String error = null;
public ResultType resultType;
public String string = null;
public long number = 0;

public BabushkaResult(String error, ResultType resultType, String string, long number) {
this.error = error;
this.resultType = resultType;
this.string = string;
this.number = number;
}

public BabushkaResult(String error, int resultType, String string, long number) {
this(error, ResultType.of(resultType), string, number);
}

// private BabushkaResult(){}

public static BabushkaResult from_str(String str) {
return BabushkaResult.builder().string(str).resultType(ResultType.STR).build();
}

public static BabushkaResult from_empty_str() {
return BabushkaResult.builder().resultType(ResultType.STR).build();
}

public static BabushkaResult from_number(long num) {
return BabushkaResult.builder().number(num).resultType(ResultType.NUM).build();
}

public static BabushkaResult from_error(String err) {
return BabushkaResult.builder().error(err).resultType(ResultType.ERR).build();
}

public static BabushkaResult from_ok() {
return BabushkaResult.builder().resultType(ResultType.OK).build();
}

public static BabushkaResult from_nil() {
return BabushkaResult.builder().resultType(ResultType.NIL).build();
}
}

public static void main(String[] args) {
var t = BabushkaResult.from_empty_str();

var ptr = init_client(42);
var a = test(ptr, "12334");
System.out.printf("Test1: %s%n", a.string);
var b = test(ptr, "abadfgdg");
System.out.printf("Test2: %s%n", b.string);

var c = connect(ptr, "redis://localhost:6379");
System.out.printf("Connect: str = %s, err = %s, type = %s%n", c.string, c.error, c.resultType);

var set = set(ptr, "JNI value", "JJJ");
System.out.printf(
"Set: str = %s, err = %s, type = %s%n", set.string, set.error, set.resultType);

var get1 = get(ptr, "JNI value");
System.out.printf(
"Get1: str = %s, err = %s, type = %s%n", get1.string, get1.error, get1.resultType);

var get2 = get(ptr, "JJJ");
System.out.printf(
"Get2: str = %s, err = %s, type = %s%n", get2.string, get2.error, get2.resultType);

int d = 5;
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,41 @@
package javababushka.benchmarks.babushka;

import javababushka.benchmarks.SyncClient;
import javababushka.benchmarks.utils.ConnectionSettings;

public class JniFfi implements SyncClient {

private long ptr = 0;

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

@Override
public void connectToRedis(ConnectionSettings connectionSettings) {
ptr = Jni.init_client(0);
Jni.connect(
ptr,
String.format(
"%s://%s:%d",
connectionSettings.useSsl ? "rediss" : "redis",
connectionSettings.host,
connectionSettings.port));
}

@Override
public String getName() {
return "JNI FFI Sync client";
}

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

@Override
public String get(String key) {
return Jni.get(ptr, key).string;
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -89,18 +89,17 @@ public static Map<ChosenAction, LatencyResults> calculateResults(
ChosenAction action = entry.getKey();
ArrayList<Long> latencies = entry.getValue();

double avgLatency =
SECONDS_IN_NANO * latencies.stream().mapToLong(Long::longValue).sum() / latencies.size();
double avgLatency = latencies.stream().mapToLong(Long::longValue).sum() / latencies.size();

Collections.sort(latencies);
results.put(
action,
new LatencyResults(
avgLatency,
SECONDS_IN_NANO * percentile(latencies, 50),
SECONDS_IN_NANO * percentile(latencies, 90),
SECONDS_IN_NANO * percentile(latencies, 99),
SECONDS_IN_NANO * stdDeviation(latencies, avgLatency)));
percentile(latencies, 50),
percentile(latencies, 90),
percentile(latencies, 99),
stdDeviation(latencies, avgLatency)));
}

return results;
Expand All @@ -111,18 +110,18 @@ public static void printResults(Map<ChosenAction, LatencyResults> resultsMap) {
ChosenAction action = entry.getKey();
LatencyResults results = entry.getValue();

System.out.println("Avg. time in ms per " + action + ": " + results.avgLatency / 1000000.0);
System.out.println(action + " p50 latency in ms: " + results.p50Latency / 1000000.0);
System.out.println(action + " p90 latency in ms: " + results.p90Latency / 1000000.0);
System.out.println(action + " p99 latency in ms: " + results.p99Latency / 1000000.0);
System.out.println(action + " std dev in ms: " + results.stdDeviation / 1000000.0);
System.out.println("Avg. time in ms per " + action + ": " + results.avgLatency / 1000000);
System.out.println(action + " p50 latency in ms: " + results.p50Latency / 1000000);
System.out.println(action + " p90 latency in ms: " + results.p90Latency / 1000000);
System.out.println(action + " p99 latency in ms: " + results.p99Latency / 1000000);
System.out.println(action + " std dev in ms: " + results.stdDeviation / 1000000);
}
}

public static void testClientSetGet(
Supplier<Client> clientCreator, BenchmarkingApp.RunConfiguration config, boolean async) {
for (int concurrentNum : config.concurrentTasks) {
int iterations = Math.min(Math.max(100000, concurrentNum * 10000), 10000000);
int iterations = 1000; // Math.min(Math.max(100000, concurrentNum * 10000), 10000000);
for (int clientCount : config.clientCount) {
for (int dataSize : config.dataSize) {
System.out.printf(
Expand Down
85 changes: 85 additions & 0 deletions java/javababushka_benchmarks_babushka_Jni.h

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

Loading

0 comments on commit 9324ba7

Please sign in to comment.