diff --git a/benchmarks/600.java/601.hello-world/config.json b/benchmarks/600.java/601.hello-world/config.json new file mode 100644 index 00000000..0c5d480e --- /dev/null +++ b/benchmarks/600.java/601.hello-world/config.json @@ -0,0 +1,6 @@ +{ + "timeout": 120, + "memory": 512, + "languages": ["java"] + } + \ No newline at end of file diff --git a/benchmarks/600.java/601.hello-world/java/pom.xml b/benchmarks/600.java/601.hello-world/java/pom.xml new file mode 100644 index 00000000..eb4f359e --- /dev/null +++ b/benchmarks/600.java/601.hello-world/java/pom.xml @@ -0,0 +1,38 @@ + + + 4.0.0 + + + faas + 601.hello-world + 1.0-SNAPSHOT + jar + + + + 1.8 + 1.8 + + + + + + + org.apache.maven.plugins + maven-jar-plugin + 3.2.0 + + + + faas.App + + + + + + + + diff --git a/benchmarks/600.java/601.hello-world/java/src/main/java/faas/App.java b/benchmarks/600.java/601.hello-world/java/src/main/java/faas/App.java new file mode 100644 index 00000000..365a6201 --- /dev/null +++ b/benchmarks/600.java/601.hello-world/java/src/main/java/faas/App.java @@ -0,0 +1,7 @@ +package faas; + +public class App { + public static void main(String[] args) { + System.out.println("Hellooooooooooooooooooo, World!"); + } +} \ No newline at end of file diff --git a/benchmarks/wrappers/openwhisk/java/Main.java b/benchmarks/wrappers/openwhisk/java/Main.java new file mode 100644 index 00000000..828aa64f --- /dev/null +++ b/benchmarks/wrappers/openwhisk/java/Main.java @@ -0,0 +1,55 @@ +import com.google.gson.JsonObject; +import com.example.project.App ; +import java.time.Instant; +import java.time.Duration; +import java.io.File; +import java.io.IOException; + + +public class Main { + public static JsonObject main(JsonObject args) { + + // Logger logger = Logger.getLogger(FunctionHandler.class.getName()); + // logger.setLevel(Level.INFO); + + Gson gson = new Gson(); + App function = new App(); + + Instant begin = Instant.now(); + JsonObject result = function.handler(args); + Instant end = Instant.now(); + + long computeTime = Duration.between(begin, end).toNanos() / 1000; // Convert nanoseconds to microseconds + + boolean isCold = false; + String fileName = "/cold_run"; + + File file = new File(fileName); + if (!file.exists()) { + isCold = true; + try { + file.createNewFile(); + } catch (IOException e) { + e.printStackTrace(); + } + } + + // Convert to Unix timestamp in seconds.microseconds + String formattedBegin = String.format("%d.%06d", begin.getEpochSecond(), begin.getNano() / 1000); // Convert nanoseconds to microseconds + String formattedEnd = String.format("%d.%06d", end.getEpochSecond(), end.getNano() / 1000); + + String requestId = System.getenv("__OW_ACTIVATION_ID"); + + JsonObject jsonResult = new JsonObject(); + jsonObject.put("begin", formattedBegin); + jsonObject.put("end", formattedEnd); + jsonObject.put("request_id", "requestId"); + jsonObject.put("compute_time", computeTime); + jsonObject.put("is_cold", isCold); + jsonObject.put("result", result); + return jsonResult; + } +} + + + \ No newline at end of file diff --git a/benchmarks/wrappers/openwhisk/java/Storage.java b/benchmarks/wrappers/openwhisk/java/Storage.java new file mode 100644 index 00000000..e69de29b diff --git a/config/example2.json b/config/example2.json new file mode 100644 index 00000000..3575d601 --- /dev/null +++ b/config/example2.json @@ -0,0 +1,69 @@ +{ + "experiments": { + "deployment": "openwhisk", + "update_code": false, + "update_storage": false, + "download_results": false, + "runtime": { + "language": "java", + "version": "8" + }, + "type": "invocation-overhead", + "perf-cost": { + "benchmark": "601.hello-world", + "experiments": ["cold", "warm", "burst", "sequential"], + "input-size": "test", + "repetitions": 50, + "concurrent-invocations": 50, + "memory-sizes": [128, 256] + }, + "network-ping-pong": { + "invocations": 50, + "repetitions": 1000, + "threads": 1 + }, + "invocation-overhead": { + "repetitions": 5, + "N": 20, + "type": "payload", + "payload_begin": 1024, + "payload_end": 6251000, + "payload_points": 20, + "code_begin": 1048576, + "code_end": 261619712, + "code_points": 20 + }, + "eviction-model": { + "invocations": 1, + "function_copy_idx": 0, + "repetitions": 5, + "sleep": 1 + } + }, + "deployment": { + "openwhisk": { + "shutdownStorage": false, + "removeCluster": false, + "wskBypassSecurity": "true", + "wskExec": "wsk", + "experimentalManifest": false, + "docker_registry": { + "registry": "", + "username": "", + "password": "" + }, + "storage": { + "address": "", + "mapped_port": 9011, + "access_key": "", + "secret_key": "", + "instance_id": "", + "output_buckets": [], + "input_buckets": [], + "type": "minio" + } + + } + } + } + \ No newline at end of file diff --git a/config/systems.json b/config/systems.json index bf095d3f..757ad388 100644 --- a/config/systems.json +++ b/config/systems.json @@ -243,6 +243,24 @@ "minio": "7.0.16" } } + }, + "java": { + "base_images": { + "8": "openwhisk/java8action" + }, + "images": [ + "function" + ], + "username": "docker_user", + "deployment": { + "files": [ + "Main.java", + "Storage.java" + ], + "packages": { + "minio": "8.5.9" + } + } } } } diff --git a/dockerfiles/openwhisk/java/Dockerfile.function b/dockerfiles/openwhisk/java/Dockerfile.function new file mode 100644 index 00000000..d86cd461 --- /dev/null +++ b/dockerfiles/openwhisk/java/Dockerfile.function @@ -0,0 +1,8 @@ +ARG BASE_IMAGE +FROM $BASE_IMAGE +COPY . /function/ + +RUN apt-get update && apt-get install -y maven + +# Check if pom.xml exists before running Maven +RUN if [ -f ./pom.xml ]; then mvn clean install; else echo "pom.xml not found, aborting build." && exit 1; fi diff --git a/sebs.py b/sebs.py index ff7f7769..bef07717 100755 --- a/sebs.py +++ b/sebs.py @@ -63,7 +63,7 @@ def simplified_common_params(func): @click.option( "--language", default=None, - type=click.Choice(["python", "nodejs"]), + type=click.Choice(["python", "nodejs", "java"]), help="Benchmark language", ) @click.option("--language-version", default=None, type=str, help="Benchmark language version") diff --git a/sebs/benchmark.py b/sebs/benchmark.py index 90eed6ae..771fde7f 100644 --- a/sebs/benchmark.py +++ b/sebs/benchmark.py @@ -250,11 +250,24 @@ def copy_code(self, output_dir): FILES = { "python": ["*.py", "requirements.txt*"], "nodejs": ["*.js", "package.json"], + "java": ["pom.xml"], } path = os.path.join(self.benchmark_path, self.language_name) + for file_type in FILES[self.language_name]: for f in glob.glob(os.path.join(path, file_type)): shutil.copy2(os.path.join(path, f), output_dir) + + # copy src folder of java (java benchmarks are maven project and need directories) + if self.language_name == "java": + output_src_dir = os.path.join(output_dir, "src") + + if os.path.exists(output_src_dir): + # If src dir in output exist, remove the directory and all its contents + shutil.rmtree(output_src_dir) + #To have contents of src directory in the direcory named src located in output + shutil.copytree(os.path.join(path, "src"), output_src_dir) + # support node.js benchmarks with language specific packages nodejs_package_json = os.path.join(path, f"package.json.{self.language_version}") if os.path.exists(nodejs_package_json): @@ -288,6 +301,16 @@ def add_deployment_files(self, output_dir): for file in handlers: shutil.copy2(file, os.path.join(output_dir)) + def add_deployment_package_java(self, output_dir): + # append to the end of requirements file + packages = self._system_config.deployment_packages( + self._deployment_name, self.language_name + ) + if len(packages): + with open(os.path.join(output_dir, "requirements.txt"), "a") as out: + for package in packages: + out.write(package) + def add_deployment_package_python(self, output_dir): # append to the end of requirements file packages = self._system_config.deployment_packages( @@ -319,6 +342,8 @@ def add_deployment_package(self, output_dir): self.add_deployment_package_python(output_dir) elif self.language == Language.NODEJS: self.add_deployment_package_nodejs(output_dir) + elif self.language == Language.JAVA: + self.add_deployment_package_java(output_dir) else: raise NotImplementedError diff --git a/sebs/faas/function.py b/sebs/faas/function.py index c2226cee..b58e9785 100644 --- a/sebs/faas/function.py +++ b/sebs/faas/function.py @@ -263,6 +263,7 @@ def deserialize(cached_config: dict) -> "Trigger": class Language(Enum): PYTHON = "python" NODEJS = "nodejs" + JAVA = "java" # FIXME: 3.7+ python with future annotations @staticmethod @@ -299,7 +300,7 @@ def serialize(self) -> dict: @staticmethod def deserialize(config: dict) -> Runtime: - languages = {"python": Language.PYTHON, "nodejs": Language.NODEJS} + languages = {"python": Language.PYTHON, "nodejs": Language.NODEJS, "java": Language.JAVA} return Runtime(language=languages[config["language"]], version=config["version"]) diff --git a/sebs/openwhisk/openwhisk.py b/sebs/openwhisk/openwhisk.py index 00660de9..01684ed3 100644 --- a/sebs/openwhisk/openwhisk.py +++ b/sebs/openwhisk/openwhisk.py @@ -168,7 +168,7 @@ def build_base_image( ) for fn in os.listdir(directory): - if fn not in ("index.js", "__main__.py"): + if fn not in ("index.js", "__main__.py", "Main.java"): file = os.path.join(directory, fn) shutil.move(file, build_dir) @@ -219,6 +219,7 @@ def package_code( CONFIG_FILES = { "python": ["__main__.py"], "nodejs": ["index.js"], + "java": ["Main.java"], } package_config = CONFIG_FILES[language_name]