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 java JNA FFI client benchmarking #28

Closed
wants to merge 2 commits into from
Closed
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
2 changes: 1 addition & 1 deletion java/.cargo/config.toml
Original file line number Diff line number Diff line change
@@ -1,3 +1,3 @@
[env]
BABUSHKA_NAME = { value = "BabushkaPy", force = true }
BABUSHKA_NAME = { value = "BabushkaJava", force = true }
BABUSHKA_VERSION = "0.1.0"
8 changes: 7 additions & 1 deletion java/Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -13,9 +13,15 @@ crate-type = ["cdylib"]
redis = { path = "../submodules/redis-rs/redis", features = ["aio", "tokio-comp", "connection-manager", "tls", "tokio-rustls-comp"] }
babushka = { path = "../babushka-core" }
tokio = { version = "^1", features = ["rt", "macros", "rt-multi-thread", "time"] }
logger_core = {path = "../logger_core"}
logger_core = { path = "../logger_core" }
tracing-subscriber = "0.3.16"
thiserror = "1.0.49"
num-derive = "0.4.1"
num-traits = "0.2.17"

[profile.release]
lto = true
debug = true

[build-dependencies]
cbindgen = "0.26.0"
2 changes: 2 additions & 0 deletions java/benchmarks/build.gradle
Original file line number Diff line number Diff line change
Expand Up @@ -18,6 +18,8 @@ dependencies {
implementation 'io.lettuce:lettuce-core:6.2.6.RELEASE'
implementation 'commons-cli:commons-cli:1.5.0'
implementation group: 'org.apache.commons', name: 'commons-lang3', version: '3.13.0'

implementation "net.java.dev.jna:jna:5.8.0"
}

// Apply a specific Java toolchain to ease working on different environments.
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -11,6 +11,7 @@
import java.util.stream.Stream;
import javababushka.benchmarks.jedis.JedisClient;
import javababushka.benchmarks.jedis.JedisPseudoAsyncClient;
import javababushka.benchmarks.jna.Babushka;
import javababushka.benchmarks.lettuce.LettuceAsyncClient;
import javababushka.benchmarks.lettuce.LettuceClient;
import org.apache.commons.cli.CommandLine;
Expand Down Expand Up @@ -53,7 +54,7 @@ public static void main(String[] args) {
testClientSetGet(LettuceAsyncClient::new, runConfiguration, true);
break;
case BABUSHKA:
System.out.println("Babushka not yet configured");
testClientSetGet(Babushka::new, runConfiguration, false);
break;
}
}
Expand Down Expand Up @@ -150,7 +151,7 @@ private static RunConfiguration verifyOptions(CommandLine line) throws ParseExce
case ALL_SYNC:
return Stream.of(
ClientName.JEDIS,
// ClientName.BABUSHKA,
ClientName.BABUSHKA,
ClientName.LETTUCE);
default:
return Stream.of(e);
Expand Down Expand Up @@ -227,8 +228,8 @@ public RunConfiguration() {
concurrentTasks = List.of(10, 100);
clients =
new ClientName[] {
// ClientName.BABUSHKA,
ClientName.JEDIS, ClientName.JEDIS_ASYNC, ClientName.LETTUCE, ClientName.LETTUCE_ASYNC
ClientName.BABUSHKA,
ClientName.JEDIS, ClientName.LETTUCE,
};
host = "localhost";
port = 6379;
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,133 @@
package javababushka.benchmarks.jna;

import com.sun.jna.Library;
import com.sun.jna.Native;
import com.sun.jna.Structure;
import javababushka.benchmarks.SyncClient;
import javababushka.benchmarks.utils.ConnectionSettings;

import java.io.IOException;
import java.nio.file.Files;
import java.nio.file.Paths;
import java.nio.file.StandardCopyOption;

public class Babushka implements SyncClient {

private final long ptr = lib.init_client0(42);

// = enum
public static enum ResultType {
Str(0),
Int(1),
Nil(2),
Data(3),
Bulk(4),
Ok(5),
Err(6),
Undef(-1);

private int id;
ResultType(int id) {
this.id = id;
}

public static ResultType of(int val) {
switch (val) {
case 0: return ResultType.Str;
case 1: return ResultType.Int;
case 2: return ResultType.Nil;
case 3: return ResultType.Data;
case 4: return ResultType.Bulk;
case 5: return ResultType.Ok;
case 6: return ResultType.Err;
default: return ResultType.Undef;
}
}
}

public interface RustLib extends Library {

@Structure.FieldOrder({"error", "value_type", "string", "num"})
public static class BabushkaResult extends Structure {
public BabushkaResult() {
error = null;
value_type = 0;
string = null;
num = 0;
}
public static class ByValue extends BabushkaResult implements Structure.ByValue { }
public String error = null;
public int value_type = 0;
public String string = null;
public long num = 0;
};

public long init_client0(int data);
public BabushkaResult.ByValue connect0(long client, String address);
public BabushkaResult.ByValue set0(long client, String key, String value);
public BabushkaResult.ByValue get0(long client, String key);
}

private static final RustLib lib;
static {
var is_win = System.getProperty("os.name").contains("Windows");
var targetDir = Paths.get("jna-stuff", "build", "resources", "main", is_win ? "win32-x86-64" : "linux-x86-64").toAbsolutePath();

//System.setProperty("jna.debug_load", "true");
System.setProperty("jna.library.path", targetDir.toString());

var created = targetDir.toFile().mkdirs();
try {
if (is_win) {
Files.copy(
Paths.get(System.getProperty("user.dir"), "target", "debug", "javababushka.dll"),
Paths.get(targetDir.toString(), "javababushka.dll"),
StandardCopyOption.REPLACE_EXISTING);
} else {
Files.copy(
Paths.get(System.getProperty("user.dir"), "..", "target", "debug", "libjavababushka.so"),
Paths.get(targetDir.toString(), "libjavababushka.so"),
StandardCopyOption.REPLACE_EXISTING);
}
} catch (IOException e) {
System.out.printf("Failed to copy lib: %s%n", e.getMessage());
e.printStackTrace();
}

lib = Native.load("javababushka", RustLib.class);
}

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

@Override
public void connectToRedis(ConnectionSettings connectionSettings) {
var connStr = String.format(
"%s://%s:%d",
connectionSettings.useSsl ? "rediss" : "redis",
connectionSettings.host,
connectionSettings.port);
lib.connect0(ptr, connStr);
}

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

@Override
public void set(String key, String value) {

}

@Override
public String get(String key) {
var res = lib.get0(ptr, key);
if (res.value_type == ResultType.Str.id) {
return res.string;
}
return res.error;
}
}
17 changes: 17 additions & 0 deletions java/build.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,17 @@
extern crate cbindgen;

use std::env;
use cbindgen::Language;

fn main() {
let crate_dir = env::var("CARGO_MANIFEST_DIR").unwrap();

cbindgen::Builder::new()
.with_crate(crate_dir)
.with_language(Language::Cxx)
//.with_cpp_compat(true)
.generate()
.expect("Unable to generate bindings")
//.write_to_file("bindings.h");
.write_to_file(format!("{}.hpp", env::var("CARGO_PKG_NAME").unwrap()));
}
Loading
Loading