From 38baa6d3a044978bef52b02320930cb432ebd2b4 Mon Sep 17 00:00:00 2001 From: Scott Trent Date: Wed, 27 Sep 2023 18:17:04 +0900 Subject: [PATCH] include helloworld micro micro benchmark --- benchmarks/README.md | 1 + benchmarks/helloworld/.gitignore | 40 +++++ benchmarks/helloworld/README.md | 60 +++++++ benchmarks/helloworld/pom.xml | 157 ++++++++++++++++++ .../helloworld/src/main/docker/Dockerfile.jvm | 34 ++++ .../src/main/docker/Dockerfile.legacy-jar | 31 ++++ .../src/main/docker/Dockerfile.native | 15 ++ .../main/docker/Dockerfile.native-distroless | 8 + .../java/com/ibm/trl/knativebench/Sleep.java | 46 +++++ .../src/main/resources/application.properties | 0 benchmarks/pom.xml | 1 + 11 files changed, 393 insertions(+) create mode 100644 benchmarks/helloworld/.gitignore create mode 100644 benchmarks/helloworld/README.md create mode 100644 benchmarks/helloworld/pom.xml create mode 100644 benchmarks/helloworld/src/main/docker/Dockerfile.jvm create mode 100644 benchmarks/helloworld/src/main/docker/Dockerfile.legacy-jar create mode 100644 benchmarks/helloworld/src/main/docker/Dockerfile.native create mode 100644 benchmarks/helloworld/src/main/docker/Dockerfile.native-distroless create mode 100644 benchmarks/helloworld/src/main/java/com/ibm/trl/knativebench/Sleep.java create mode 100644 benchmarks/helloworld/src/main/resources/application.properties diff --git a/benchmarks/README.md b/benchmarks/README.md index 4320d8f..af4a287 100644 --- a/benchmarks/README.md +++ b/benchmarks/README.md @@ -13,6 +13,7 @@ described in [UsingCloudObjectStorage.md](UsingCloudObjectStorage.md). |graph-bfs |Traverse a generated graph in breadth-first order | N | |graph-mst |Compute minimum spanning tree of a generated graph | N | |graph-pagerank |Compute page rank scores of a generated graph | N | +|helloworld |A very simple benchmark that creates a string | N | |image-recognition |Image classification using a deep learning model from Model Zoo| Y | |network |Repeatedly measure send and receive time of a datagram socket | Y | |server-reply |Measure time to read a stream socket | N | diff --git a/benchmarks/helloworld/.gitignore b/benchmarks/helloworld/.gitignore new file mode 100644 index 0000000..de3275c --- /dev/null +++ b/benchmarks/helloworld/.gitignore @@ -0,0 +1,40 @@ +#Maven +target/ +pom.xml.tag +pom.xml.releaseBackup +pom.xml.versionsBackup +release.properties +.mvn/ + +# Eclipse +.project +.classpath +.settings/ +bin/ + +# IntelliJ +.idea +*.ipr +*.iml +*.iws + +# NetBeans +nb-configuration.xml + +# Visual Studio Code +.vscode +.factorypath + +# OSX +.DS_Store + +# Vim +*.swp +*.swo + +# patch +*.orig +*.rej + +# Local environment +.env diff --git a/benchmarks/helloworld/README.md b/benchmarks/helloworld/README.md new file mode 100644 index 0000000..ee88f0e --- /dev/null +++ b/benchmarks/helloworld/README.md @@ -0,0 +1,60 @@ +# helloworld Project + +This is a project to port and test [serverless-benchmarks](https://github.com/spcl/serverless-benchmarks) using Quarkus +[Funqy HTTP Binding](https://quarkus.io/guides/funqy-http), which creates a stand-alone application using serverless functions. + +To learn more about Quarkus, please refer to https://quarkus.io/ . + +## Packaging and running the application + +The application can be packaged using: +```shell script +mvn -Dskiptests clean package +``` +This produces the `quarkus-run.jar` file in the `target/quarkus-app/` directory. +Be aware that this is not an _über-jar_ as the dependencies are copied into the `target/quarkus-app/lib/` directory. + +The application is runnable using: +```shell script +java -jar target/quarkus-app/quarkus-run.jar +``` + +The server listens to `localhost:8080`, and functions are accessible at `/` path. +Functions with parameters only accept POST requests. Functions without parameters accept both GET and POST requests. + +Sample curl command for testing the `/helloworld` function: +``` +curl -s -w "\n" -H 'Content-Type:application/json' -d '"test"' -X POST http://localhost:8080/helloworld | jq +``` +The result looks like: +``` +{ + "result": 1 +} +``` +Valid choices of the test data size are `test`, `small`, and `large`, where the graph sizes are set to `1`, `100`, and `1,000`, respectively. + +### Building an über-jar +To build an _über-jar_, execute the following command: +```shell script +mvn package -Dquarkus.package.type=uber-jar +``` + +The application, packaged as an _über-jar_, is runnable using `java -jar target/*-runner.jar`. + +## Creating a native executable + +To build a native executable: +```shell script +mvn package -Pnative +``` + +If GraalVM is not installed, the native executable can be built in a container using: +```shell script +mvn package -Pnative -Dquarkus.native.container-build=true +``` + +To run the native image: `./target/helloworld-1.0.0-SNAPSHOT-runner` + +To learn more about building native executables, please consult https://quarkus.io/guides/maven-tooling.html. + diff --git a/benchmarks/helloworld/pom.xml b/benchmarks/helloworld/pom.xml new file mode 100644 index 0000000..6a6f8b6 --- /dev/null +++ b/benchmarks/helloworld/pom.xml @@ -0,0 +1,157 @@ + + + 4.0.0 + + com.ibm.trl + benchmarks + 1.0.0-SNAPSHOT + + com.ibm.trl + helloworld + 1.0.0-SNAPSHOT + + + + ${quarkus.platform.group-id} + ${quarkus.platform.artifact-id} + ${quarkus.platform.version} + pom + import + + + + + + io.quarkus + quarkus-funqy-knative-events + + + io.quarkus + quarkus-arc + + + io.quarkus + quarkus-resteasy-jackson + + + io.quarkus + quarkus-container-image-docker + + + io.quarkus + quarkus-junit5 + test + + + io.rest-assured + rest-assured + test + + + + + + ${quarkus.platform.group-id} + quarkus-maven-plugin + ${quarkus.platform.version} + true + + + + build + generate-code + generate-code-tests + + + + + + maven-compiler-plugin + ${compiler-plugin.version} + + ${maven.compiler.parameters} + true + lines,vars,source + + + + maven-surefire-plugin + ${surefire-plugin.version} + + + org.jboss.logmanager.LogManager + ${maven.home} + + + + + com.coderplus.maven.plugins + copy-rename-maven-plugin + 1.0 + + + copy-file + generate-sources + + copy + + + + + ${java.home}/lib/security/cacerts + target/cacerts + + + + + + + + + + + native + + + native + + + + + + maven-failsafe-plugin + ${surefire-plugin.version} + + + + integration-test + verify + + + + ${project.build.directory}/${project.build.finalName}-runner + org.jboss.logmanager.LogManager + ${maven.home} + + + + + + + + + native + + + + qbicc + + + org.qbicc.quarkus + quarkus-qbicc + + + + + diff --git a/benchmarks/helloworld/src/main/docker/Dockerfile.jvm b/benchmarks/helloworld/src/main/docker/Dockerfile.jvm new file mode 100644 index 0000000..fed0936 --- /dev/null +++ b/benchmarks/helloworld/src/main/docker/Dockerfile.jvm @@ -0,0 +1,34 @@ +#### +# This Dockerfile is used in order to build a container that runs the Quarkus application in JVM mode +### +FROM registry.access.redhat.com/ubi8/ubi-minimal:8.8 + +ARG JAVA_PACKAGE=java-17-openjdk-headless +ARG RUN_JAVA_VERSION=1.3.8 +ENV LANG='en_US.UTF-8' LANGUAGE='en_US:en' +# Install java and the run-java script +# Also set up permissions for user `1001` +RUN microdnf --disablerepo='*' --enablerepo='ubi-8-*' install curl ca-certificates ${JAVA_PACKAGE} \ + && microdnf --disablerepo='*' --enablerepo='ubi-8-*' update \ + && microdnf --disablerepo='*' --enablerepo='ubi-8-*' clean all \ + && mkdir /deployments \ + && chown 1001 /deployments \ + && chmod "g+rwX" /deployments \ + && chown 1001:root /deployments \ + && curl https://repo1.maven.org/maven2/io/fabric8/run-java-sh/${RUN_JAVA_VERSION}/run-java-sh-${RUN_JAVA_VERSION}-sh.sh -o /deployments/run-java.sh \ + && chown 1001 /deployments/run-java.sh \ + && chmod 540 /deployments/run-java.sh \ + && echo "securerandom.source=file:/dev/urandom" >> /etc/alternatives/jre/conf/security/java.security + +# Configure the JAVA_OPTIONS, you can add -XshowSettings:vm to also display the heap size. +ENV JAVA_OPTIONS="-Dquarkus.http.host=0.0.0.0 -Djava.util.logging.manager=org.jboss.logmanager.LogManager" +# We make four distinct layers so if there are application changes the library layers can be re-used +COPY --chown=1001 target/quarkus-app/lib/ /deployments/lib/ +COPY --chown=1001 target/quarkus-app/*.jar /deployments/ +COPY --chown=1001 target/quarkus-app/app/ /deployments/app/ +COPY --chown=1001 target/quarkus-app/quarkus/ /deployments/quarkus/ + +EXPOSE 8080 +USER 1001 + +ENTRYPOINT [ "sh", "-c", "grep 'model name' /proc/cpuinfo | head -1; /deployments/run-java.sh" ] diff --git a/benchmarks/helloworld/src/main/docker/Dockerfile.legacy-jar b/benchmarks/helloworld/src/main/docker/Dockerfile.legacy-jar new file mode 100644 index 0000000..13cc0be --- /dev/null +++ b/benchmarks/helloworld/src/main/docker/Dockerfile.legacy-jar @@ -0,0 +1,31 @@ +#### +# This Dockerfile is used in order to build a container that runs the Quarkus application in JVM mode +### +FROM registry.access.redhat.com/ubi8/ubi-minimal:8.8 + +ARG JAVA_PACKAGE=java-17-openjdk-headless +ARG RUN_JAVA_VERSION=1.3.8 +ENV LANG='en_US.UTF-8' LANGUAGE='en_US:en' +# Install java and the run-java script +# Also set up permissions for user `1001` +RUN microdnf --disablerepo='*' --enablerepo='ubi-8-*' install curl ca-certificates ${JAVA_PACKAGE} \ + && microdnf --disablerepo='*' --enablerepo='ubi-8-*' update \ + && microdnf --disablerepo='*' --enablerepo='ubi-8-*' clean all \ + && mkdir /deployments \ + && chown 1001 /deployments \ + && chmod "g+rwX" /deployments \ + && chown 1001:root /deployments \ + && curl https://repo1.maven.org/maven2/io/fabric8/run-java-sh/${RUN_JAVA_VERSION}/run-java-sh-${RUN_JAVA_VERSION}-sh.sh -o /deployments/run-java.sh \ + && chown 1001 /deployments/run-java.sh \ + && chmod 540 /deployments/run-java.sh \ + && echo "securerandom.source=file:/dev/urandom" >> /etc/alternatives/jre/conf/security/java.security + +# Configure the JAVA_OPTIONS, you can add -XshowSettings:vm to also display the heap size. +ENV JAVA_OPTIONS="-Dquarkus.http.host=0.0.0.0 -Djava.util.logging.manager=org.jboss.logmanager.LogManager" +COPY target/lib/* /deployments/lib/ +COPY target/*-runner.jar /deployments/app.jar + +EXPOSE 8080 +USER 1001 + +ENTRYPOINT [ "/deployments/run-java.sh" ] diff --git a/benchmarks/helloworld/src/main/docker/Dockerfile.native b/benchmarks/helloworld/src/main/docker/Dockerfile.native new file mode 100644 index 0000000..d2c2bd4 --- /dev/null +++ b/benchmarks/helloworld/src/main/docker/Dockerfile.native @@ -0,0 +1,15 @@ +#### +# This Dockerfile is used in order to build a container that runs the Quarkus application in native (no JVM) mode +### +FROM registry.access.redhat.com/ubi8/ubi-minimal:8.8 +WORKDIR /work/ +RUN chown 1001 /work \ + && chmod "g+rwX" /work \ + && chown 1001:root /work +COPY --chown=1001:root target/*-runner /work/application + +EXPOSE 8080 +USER 1001 + +ENV JAVA_OPTIONS -Dquarkus.http.host=0.0.0.0 +CMD ["sh", "-c", "grep 'model name' /proc/cpuinfo | head -1; ./application ${JAVA_OPTIONS}"] diff --git a/benchmarks/helloworld/src/main/docker/Dockerfile.native-distroless b/benchmarks/helloworld/src/main/docker/Dockerfile.native-distroless new file mode 100644 index 0000000..4e39e10 --- /dev/null +++ b/benchmarks/helloworld/src/main/docker/Dockerfile.native-distroless @@ -0,0 +1,8 @@ +FROM quay.io/quarkus/quarkus-distroless-image:1.0 +COPY target/*-runner /application + +EXPOSE 8080 +USER nonroot + +ENV JAVA_OPTIONS -Dquarkus.http.host=0.0.0.0 +CMD ["sh", "-c", "./application ${JAVA_OPTIONS}"] diff --git a/benchmarks/helloworld/src/main/java/com/ibm/trl/knativebench/Sleep.java b/benchmarks/helloworld/src/main/java/com/ibm/trl/knativebench/Sleep.java new file mode 100644 index 0000000..9e88235 --- /dev/null +++ b/benchmarks/helloworld/src/main/java/com/ibm/trl/knativebench/Sleep.java @@ -0,0 +1,46 @@ +package com.ibm.trl.knativebench; + +import java.util.HashMap; +import java.util.Map; +import java.util.concurrent.TimeUnit; + +import javax.inject.Inject; + +import org.jboss.logging.Logger; + +import io.quarkus.funqy.Funq; + +public class Sleep { + static double nanosecInSec = 1_000_000_000.0; + static Map size_generators = Map.of("test", 1, + "small", 100, + "large", 1000); + @Inject + Logger log; + + @Funq + public HashMap helloworld(String size) { + HashMap retVal = new HashMap(); + long hello_count = 0; + + if (size != null) { + Integer hc = size_generators.get(size); + if (hc != null) { + hello_count = hc.intValue(); + } + } + long processTimeBegin = System.nanoTime(); + + String hello = "world!"; + for (int i = 0; i