Skip to content

New benchmarks in java #222

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

Open
wants to merge 26 commits into
base: java_benchmarks_support
Choose a base branch
from
Open
Changes from all commits
Commits
Show all changes
26 commits
Select commit Hold shift + click to select a range
a9b41f1
Add base image for Java benchmarks on OpenWhisk
mahlashrifi Sep 8, 2024
b0e0483
Add Dockerfile for running Java benchmarks on OpenWhisk
mahlashrifi Sep 8, 2024
f9db755
Update base image of java on OpenWhisk
mahlashrifi Sep 8, 2024
b1307e1
Add Java-based handler for OpenWhisk
mahlashrifi Sep 10, 2024
29e7d3f
Add example config file for running java benchmarks on OpenWhisk
mahlashrifi Sep 19, 2024
bced306
Add JAVA enum to list of languages
mahlashrifi Sep 19, 2024
3c53e5f
Add config of 601.hello-world (A simple java benchmark)
mahlashrifi Sep 19, 2024
49deef7
Init maven structure of 601.hello-world and add some codes for runnin…
mahlashrifi Sep 19, 2024
722b447
Sync hello-world maven paroject with the wrapper of openwhisk
mahlashrifi Sep 19, 2024
930813e
Example config file for running 601.hello-world on openwhisk
mahlashrifi Sep 23, 2024
f295e01
Correct Structure of maven project in 601.hello-world benchmark
mahlashrifi Sep 23, 2024
0fa43be
Expand add_code functions for maven java rojects
mahlashrifi Sep 23, 2024
3fb661f
Exclude Java main wrapper from Docker directory created in runtimes.
mahlashrifi Sep 23, 2024
a14d0a0
Fix a big
mahlashrifi Sep 25, 2024
aab419d
making jar file is working correctly
mahlashrifi Sep 25, 2024
a80e91f
loginChecker running successfly on openwhisk
mahlashrifi Sep 25, 2024
686b536
Update config.json
mahlashrifi Oct 6, 2024
4f24bd3
Add all codes
mahlashrifi Oct 17, 2024
c019089
Merge branch 'java_benchmarks_support' of github.com:mahlashrifi/serv…
mahlashrifi Oct 17, 2024
a6ec3f5
Remove .vscode folder from the repository and add it to .gitignore
mahlashrifi Dec 25, 2024
fbc34a8
Removed out_storage.json
mahlashrifi Dec 25, 2024
29e3529
Refactored OpenWhisk run command handling for Java functions
mahlashrifi Dec 26, 2024
1a1a647
Removed repo name from system.json file
mahlashrifi Dec 26, 2024
4e997ef
Removed config files mistakenly committed.
mahlashrifi Dec 26, 2024
fbeaa89
Reverted config file to remove unintended changes.
mahlashrifi Dec 26, 2024
28b4e92
Remove redundant benchmarks
mahlashrifi Feb 4, 2025
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
3 changes: 3 additions & 0 deletions .gitignore
Original file line number Diff line number Diff line change
@@ -182,3 +182,6 @@ cache
# IntelliJ IDEA files
.idea
*.iml

# Visual Studio Code files
.vscode/
6 changes: 6 additions & 0 deletions benchmarks/600.java/601.hello-world/config.json
Original file line number Diff line number Diff line change
@@ -0,0 +1,6 @@
{
"timeout": 120,
"memory": 512,
"languages": ["java"]
}

Empty file.
38 changes: 38 additions & 0 deletions benchmarks/600.java/601.hello-world/java/pom.xml
Original file line number Diff line number Diff line change
@@ -0,0 +1,38 @@
<project xmlns="http://maven.apache.org/POM/4.0.0"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://maven.apache.org/POM/4.0.0
http://maven.apache.org/xsd/maven-4.0.0.xsd">

<modelVersion>4.0.0</modelVersion>

<!-- Group ID and Artifact ID uniquely identify the project -->
<groupId>faas</groupId>
<artifactId>601.hello-world</artifactId>
<version>1.0-SNAPSHOT</version>
<packaging>jar</packaging> <!-- The packaging type for the project (jar by default) -->

<!-- Configure the Java version (set to Java 8) -->
<properties>
<maven.compiler.source>1.8</maven.compiler.source> <!-- Source compatibility (Java 8) -->
<maven.compiler.target>1.8</maven.compiler.target> <!-- Target compatibility (Java 8) -->
</properties>

<!-- Define the main class to run the JAR -->
<build>
<plugins>
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-jar-plugin</artifactId>
<version>3.2.0</version>
<configuration>
<archive>
<manifest>
<mainClass>faas.App</mainClass> <!-- Replace with your main class -->
</manifest>
</archive>
</configuration>
</plugin>
</plugins>
</build>
</project>

Original file line number Diff line number Diff line change
@@ -0,0 +1,7 @@
package faas;

public class App {
public static void main(String[] args) {
System.out.println("Hellooooooooooooooooooo, World!");
}
}
6 changes: 6 additions & 0 deletions benchmarks/600.java/602.login-checker/config.json
Original file line number Diff line number Diff line change
@@ -0,0 +1,6 @@
{
"timeout": 60,
"memory": 24,
Copy link
Collaborator

Choose a reason for hiding this comment

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

this doesn't appear to be a correct value - is it really just 24 MB?

Copy link
Collaborator Author

Choose a reason for hiding this comment

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

Thanks for asking. I wasn’t sure. Now the benchmark is running correctly without any errors, but in general, how should I find this value?

Copy link
Collaborator

Choose a reason for hiding this comment

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

This needs to be found experimentally as it differs per each benchmark

I'm also not sure if we even set this up on OpenWhisk.

Copy link
Collaborator Author

Choose a reason for hiding this comment

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

I will check it. thanks.

"languages": ["java"]
}

5 changes: 5 additions & 0 deletions benchmarks/600.java/602.login-checker/input.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
def buckets_count():
return (0, 0)

def generate_input(data_dir, size, benchmarks_bucket, input_paths, output_paths, upload_func):
return { }
58 changes: 58 additions & 0 deletions benchmarks/600.java/602.login-checker/java/pom.xml
Original file line number Diff line number Diff line change
@@ -0,0 +1,58 @@
<?xml version="1.0" encoding="UTF-8"?>
<project xmlns="http://maven.apache.org/POM/4.0.0"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
<modelVersion>4.0.0</modelVersion>

<groupId>faas</groupId>
<artifactId>benchmark</artifactId>
<version>1</version>

<properties>
<maven.compiler.source>8</maven.compiler.source>
<maven.compiler.target>8</maven.compiler.target>
<project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
</properties>

<dependencies>
<!-- https://mvnrepository.com/artifact/com.google.code.gson/gson -->
<dependency>
<groupId>com.google.code.gson</groupId>
<artifactId>gson</artifactId>
<version>2.11.0</version>
</dependency>
<!-- &lt;!&ndash; https://mvnrepository.com/artifact/com.fasterxml.jackson.core/jackson-databind &ndash;&gt;-->
<dependency>
<groupId>com.fasterxml.jackson.core</groupId>
<artifactId>jackson-databind</artifactId>
<version>2.17.2</version>
</dependency>
<!-- https://mvnrepository.com/artifact/com.fasterxml.jackson.core/jackson-core -->
<dependency>
<groupId>com.fasterxml.jackson.core</groupId>
<artifactId>jackson-core</artifactId>
<version>2.17.2</version>
</dependency>

</dependencies>
<build>
<plugins>
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-shade-plugin</artifactId>
<version>3.2.4</version>
<executions>
<execution>
<phase>package</phase>
<goals>
<goal>shade</goal>
</goals>
<configuration>
<createDependencyReducedPom>false</createDependencyReducedPom>
</configuration>
</execution>
</executions>
</plugin>
</plugins>
</build>
</project>
Original file line number Diff line number Diff line change
@@ -0,0 +1,26 @@
package faas;
import com.google.gson.Gson;
import com.google.gson.JsonObject;
import util.SessionBlob;
import util.ShaSecurityProvider;

//import jakarta.ws.rs.core.Response;


public class App {
public JsonObject handler(JsonObject args) {
Gson gson = new Gson();
SessionBlob blob = gson.fromJson(args, SessionBlob.class);

ShaSecurityProvider securityProvider = new ShaSecurityProvider();
SessionBlob validatedBlob = securityProvider.validate(blob);

JsonObject jsonResult = new JsonObject();
if (validatedBlob != null)
jsonResult.addProperty("Authorization-Status", "Authorized");
else
jsonResult.addProperty("Authorization-Status", "Unauthorized");
return jsonResult;
}
}

Original file line number Diff line number Diff line change
@@ -0,0 +1,21 @@
package util;


/**
* Class for testing. Provides a constant key. DO NOT ADOPT THIS FOR ANY REAL
* PRODUCTION WORKLOAD!
*
* @author Joakim von Kistowski
*
*/
public class ConstantKeyProvider implements IKeyProvider {

/**
* {@inheritDoc}
*/
@Override
public String getKey(SessionBlob blob) {
return "thebestsecretkey";
}

}
Original file line number Diff line number Diff line change
@@ -0,0 +1,23 @@

package util;

/**
* Provides keys for the security provider. The key provider must ensure that
* keys accross replicated stores are consistent.
*
* @author Joakim von Kistowski
*
*/
public interface IKeyProvider {

/**
* Returns a key for a session blob. Key must be the same, regardless of the
* store instance upon which this call is made.
*
* @param blob
* The blob to secure.
* @return The key.
*/
public String getKey(SessionBlob blob);

}
Original file line number Diff line number Diff line change
@@ -0,0 +1,39 @@
package util;


/**
* Utilities for securing (e.g. encrypting) session blobs.
*
* @author Joakim von Kistowski
*
*/
public interface ISecurityProvider {

/**
* Get the key provider for this security provider.
*
* @return The key provider.
*/
public IKeyProvider getKeyProvider();

/**
* Secures a session blob. May encrypt or hash values within the blob.
*
* @param blob
* The blob to secure.
* @return A secure blob to be passed on to the web ui.
*/
public SessionBlob secure(SessionBlob blob);

/**
* Validates a secured session blob. Returns a valid and readable (e.g.
* decrypted) blob. Returns null for invalid blobs.
*
* @param blob
* The blob to secure.
* @return The valid and readable (e.g. decrypted) blob. Returns null for
* invalid blobs.
*/
public SessionBlob validate(SessionBlob blob);

}
Original file line number Diff line number Diff line change
@@ -0,0 +1,281 @@

package util;

/**
* Entity for orders.
*
* @author Joakim von Kistowski
*
*/
public class Order {

private long id;
private long userId;
private String time;

private long totalPriceInCents;
private String addressName;
private String address1;
private String address2;

private String creditCardCompany;
private String creditCardNumber;
private String creditCardExpiryDate;

/**
* Create a new and empty order.
*/
public Order() {

}

/**
* Every entity needs a copy constructor.
*
* @param order
* The order to copy.
*/
public Order(Order order) {
setId(order.getId());
setUserId(order.getUserId());
setTime(order.getTime());
setTotalPriceInCents(order.getTotalPriceInCents());
setAddressName(order.getAddressName());
setAddress1(order.getAddress1());
setAddress2(order.getAddress2());
setCreditCardCompany(order.getCreditCardCompany());
setCreditCardNumber(order.getCreditCardNumber());
setCreditCardExpiryDate(order.getCreditCardExpiryDate());
}

/**
* Get the id (remember that this ID may be incorrect, especially if a separate id was passed).
*
* @return The id.
*/
public long getId() {
return id;
}

/**
* For REST use only. Sets the ID. Ignored by persistence.
*
* @param id
* ID, as passed by the REST API.
*/
public void setId(long id) {
this.id = id;
}

/**
* Get the User id.
*
* @return the userId.
*/
public long getUserId() {
return userId;
}

/**
* Set the User Id.
*
* @param userId
* the userId to set.
*/
public void setUserId(long userId) {
this.userId = userId;
}

/**
* Get the time of order (ISO formatted). Formatted using {@link DateTimeFormatter.ISO_LOCAL_DATE_TIME}.
*
* @return the time.
*/
public String getTime() {
return time;
}

/**
* Set the time of order (ISO formatted). Format using {@link DateTimeFormatter.ISO_LOCAL_DATE_TIME}.
*
* @param time
* the time to set.
*/
public void setTime(String time) {
this.time = time;
}

/**
* Get the total price in cents.
*
* @return the totalPriceInCents.
*/
public long getTotalPriceInCents() {
return totalPriceInCents;
}

/**
* Set the total price in cents.
*
* @param totalPriceInCents
* the totalPriceInCents to set.
*/
public void setTotalPriceInCents(long totalPriceInCents) {
this.totalPriceInCents = totalPriceInCents;
}

/**
* Get the name for the address.
*
* @return the addressName.
*/
public String getAddressName() {
return addressName;
}

/**
* Set the name for the address.
*
* @param addressName
* the addressName to set.
*/
public void setAddressName(String addressName) {
this.addressName = addressName;
}

/**
* Get address line 1.
*
* @return the address1.
*/
public String getAddress1() {
return address1;
}

/**
* Set address line 1.
*
* @param address1
* the address1 to set.
*/
public void setAddress1(String address1) {
this.address1 = address1;
}

/**
* Get address line 2.
*
* @return the address2.
*/
public String getAddress2() {
return address2;
}

/**
* Set address line 2.
*
* @param address2
* the address2 to set.
*/
public void setAddress2(String address2) {
this.address2 = address2;
}

/**
* Get the name of the credit card company.
*
* @return the creditCardCompany.
*/
public String getCreditCardCompany() {
return creditCardCompany;
}

/**
* Set the name of the credit card company.
*
* @param creditCardCompany
* the creditCardCompany to set.
*/
public void setCreditCardCompany(String creditCardCompany) {
this.creditCardCompany = creditCardCompany;
}

/**
* Get the credit card number.
*
* @return the creditCardNumber.
*/
public String getCreditCardNumber() {
return creditCardNumber;
}

/**
* Set the credit card number.
*
* @param creditCardNumber
* the creditCardNumber to set.
*/
public void setCreditCardNumber(String creditCardNumber) {
this.creditCardNumber = creditCardNumber;
}

/**
* Get the credit card expiry date (ISO formatted). Formatted using {@link DateTimeFormatter.ISO_LOCAL_DATE}.
*
* @return the creditCardExpiryDate.
*/
public String getCreditCardExpiryDate() {
return creditCardExpiryDate;
}

/**
* Set the credit card expiry date (ISO formatted). Format using {@link DateTimeFormatter.ISO_LOCAL_DATE}.
*
* @param creditCardExpiryDate
* the creditCardExpiryDate to set.
*/
public void setCreditCardExpiryDate(String creditCardExpiryDate) {
this.creditCardExpiryDate = creditCardExpiryDate;
}

/*
* (non-Javadoc)
*
* @see java.lang.Object#hashCode()
*/
@Override
public int hashCode() {
final int prime = 31;
int result = 1;
result = prime * result + (int) (id ^ (id >>> 32));
result = prime * result + (int) (userId ^ (userId >>> 32));
return result;
}

/*
* (non-Javadoc)
*
* @see java.lang.Object#equals(java.lang.Object)
*/
@Override
public boolean equals(Object obj) {
if (this == obj) {
return true;
}
if (obj == null) {
return false;
}
if (getClass() != obj.getClass()) {
return false;
}
Order other = (Order) obj;
if (id != other.id) {
return false;
}
if (userId != other.userId) {
return false;
}
return true;
}

}
Original file line number Diff line number Diff line change
@@ -0,0 +1,179 @@

package util;

/**
* Entity Class for OrderItems (item with quantity in shopping cart or order).
*
* @author Joakim von Kistowski
*
*/
public class OrderItem {

private long id;
private long productId;
private long orderId;
private int quantity;
private long unitPriceInCents;

/**
* Create a new and empty OrderItem.
*/
public OrderItem() {

}

/**
* Every Entity needs a Copy-Constructor!
*
* @param orderItem
* The entity to Copy.
*/
public OrderItem(OrderItem orderItem) {
setId(orderItem.getId());
setProductId(orderItem.getProductId());
setOrderId(orderItem.getOrderId());
setQuantity(orderItem.getQuantity());
setUnitPriceInCents(orderItem.getUnitPriceInCents());
}

/**
* Get the id (remember that this ID may be incorrect, especially if a separate id was passed).
*
* @return The id.
*/
public long getId() {
return id;
}

/**
* For REST use only. Sets the ID. Ignored by persistence.
*
* @param id
* ID, as passed by the REST API.
*/
public void setId(long id) {
this.id = id;
}

/**
* ID of the order item's product.
*
* @return Product Id;
*/
public long getProductId() {
return productId;
}

/**
* Sets the ID of the order item's product. Every order Item MUST have a valid product ID.
*
* @param productId
* The product ID to set.
*/
public void setProductId(long productId) {
this.productId = productId;
}

/**
* Get the quantity (amount in shopping cart/order).
*
* @return The quantity.
*/
public int getQuantity() {
return quantity;
}

/**
* Set the quantity (amount in shopping cart/order).
*
* @param quantity
* The quantity.
*/
public void setQuantity(int quantity) {
this.quantity = quantity;
}

/**
* The price per single item in the order item.
*
* @return Price per single item.
*/
public long getUnitPriceInCents() {
return unitPriceInCents;
}

/**
* Set the price per single item in the order item.
*
* @param unitPriceInCents
* Price per single item.
*/
public void setUnitPriceInCents(long unitPriceInCents) {
this.unitPriceInCents = unitPriceInCents;
}

/**
* Gets the ID of the order item's order.
*
* @return The order ID.
*/
public long getOrderId() {
return orderId;
}

/**
* Sets the ID of the order item's order. Persistence requires that every order item MUST have a valid order ID. For
* persistence the order must already exist in database.
*
* @param orderId
* The order ID to set.
*/
public void setOrderId(long orderId) {
this.orderId = orderId;
}

/*
* (non-Javadoc)
*
* @see java.lang.Object#hashCode()
*/
@Override
public int hashCode() {
final int prime = 31;
int result = 1;
result = prime * result + (int) (id ^ (id >>> 32));
result = prime * result + (int) (orderId ^ (orderId >>> 32));
result = prime * result + (int) (productId ^ (productId >>> 32));
return result;
}

/*
* (non-Javadoc)
*
* @see java.lang.Object#equals(java.lang.Object)
*/
@Override
public boolean equals(Object obj) {
if (this == obj) {
return true;
}
if (obj == null) {
return false;
}
if (getClass() != obj.getClass()) {
return false;
}
OrderItem other = (OrderItem) obj;
if (id != other.id) {
return false;
}
if (orderId != other.orderId) {
return false;
}
if (productId != other.productId) {
return false;
}
return true;
}

}
Original file line number Diff line number Diff line change
@@ -0,0 +1,133 @@
package util;

import java.util.LinkedList;
import java.util.List;

/**
* Blob containing all information about the user session.
* @author Simon
*/
public class SessionBlob {

private Long uid;
private String sid;
private String token;
private Order order;
private List<OrderItem> orderItems = new LinkedList<OrderItem>();
private String message;

/**
* Constructor, creates an empty order.
*/
public SessionBlob() {
this.setOrder(new Order());
}

/**
* Getter for the userid.
* @return userid
*/
public Long getUID() {
return uid;
}

/**
* Setter for the userid.
* @param uID userid
*/
public void setUID(Long uID) {
uid = uID;
}

/**
* Getter for session id.
* @return session id
*/
public String getSID() {
return sid;
}

/**
* Setter for session id.
* @param sID session id
*/
public void setSID(String sID) {
sid = sID;
}

/**
* Getter for trust token.
* @return trust token
*/
public String getToken() {
return token;
}

/**
* Setter for trust token.
* @param token trust token.
*/
public void setToken(String token) {
this.token = token;
}

/**
* Setter for the message.
* @param message String
*/
public void setMessage(String message) {
this.message = message;
}

/**
* Getter for the message.
* @return message
*/
public String getMessage() {
return message;
}

/**
* Getter for order.
* @return order
*/
public Order getOrder() {
return order;
}

/**
* Setter for order.
* @param order order
*/
public void setOrder(Order order) {
this.order = order;
}

/**
* Getter for order items.
* @return order items.
*/
public List<OrderItem> getOrderItems() {
return orderItems;
}

/**
* Setter for order items.
* @param orderItems list of order items
*/
public void setOrderItems(List<OrderItem> orderItems) {
this.orderItems = orderItems;
}

@Override
public String toString() {
return "ClassName{" +
"uid=" + uid +
", sid='" + sid + '\'' +
", token='" + token + '\'' +
", order=" + (order != null ? order.toString() : "null") +
", orderItems=" + (orderItems != null ? orderItems.toString() : "null") +
", message='" + message + '\'' +
'}';
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,79 @@
package util;

import java.io.UnsupportedEncodingException;

import com.fasterxml.jackson.core.JsonProcessingException;
import com.fasterxml.jackson.databind.ObjectMapper;

import java.net.URLEncoder;
import java.security.MessageDigest;
import java.security.NoSuchAlgorithmException;

/**
* Secruity provider uscom.fasterxml.jackson.databind.Objecting AES.
*
* @author Simon
*
*/
public class ShaSecurityProvider implements ISecurityProvider {

@Override
public IKeyProvider getKeyProvider() {
return new ConstantKeyProvider();
}

@Override
public SessionBlob secure(SessionBlob blob) {
if (blob.getUID() == null || blob.getSID() == null) {
return blob;
}
blob.setToken(null);
String blobString = blobToString(blob);
blob.setToken(getSha512(blobString));
return blob;
}

private String blobToString(SessionBlob blob) {
ObjectMapper o = new ObjectMapper();
try {
return URLEncoder.encode(o.writeValueAsString(blob), "UTF-8");
} catch (JsonProcessingException | UnsupportedEncodingException e)
{
throw new IllegalStateException("Could not save blob!");
}
}

@Override
public SessionBlob validate(SessionBlob blob) {
if (blob.getToken() == null) {
return null;
}

String token = blob.getToken();
blob.setToken(null);
String blobString = blobToString(blob);
String validationToken = getSha512(blobString);
if (validationToken.equals(token)) {
return blob;
}
return null;
}

private String getSha512(String passwordToHash) {
String generatedPassword = null;
try {
String salt = getKeyProvider().getKey(null);
MessageDigest md = MessageDigest.getInstance("SHA-512");
md.update(salt.getBytes("UTF-8"));
byte[] bytes = md.digest(passwordToHash.getBytes("UTF-8"));
StringBuilder sb = new StringBuilder();
for (int i = 0; i < bytes.length; i++) {
sb.append(Integer.toString((bytes[i] & 0xff) + 0x100, 16).substring(1));
}
generatedPassword = sb.toString();
} catch (NoSuchAlgorithmException | UnsupportedEncodingException e) {
e.printStackTrace();
}
return generatedPassword;
}
}
6 changes: 6 additions & 0 deletions benchmarks/600.java/603.train-recommender/config.json
Original file line number Diff line number Diff line change
@@ -0,0 +1,6 @@
{
"timeout": 60,
"memory": 512,
"languages": ["java"]
}

5 changes: 5 additions & 0 deletions benchmarks/600.java/603.train-recommender/input.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
def buckets_count():
return (0, 0)

def generate_input(data_dir, size, benchmarks_bucket, input_paths, output_paths, upload_func):
return {"orderItems":[{"id":0,"productId":201,"orderId":1,"quantity":2,"unitPriceInCents":0},{"id":0,"productId":202,"orderId":1,"quantity":1,"unitPriceInCents":0},{"id":0,"productId":203,"orderId":2,"quantity":5,"unitPriceInCents":0}],"orders":[{"id":1,"userId":101,"totalPriceInCents":0},{"id":2,"userId":102,"totalPriceInCents":0}]}
46 changes: 46 additions & 0 deletions benchmarks/600.java/603.train-recommender/java/pom.xml
Original file line number Diff line number Diff line change
@@ -0,0 +1,46 @@
<?xml version="1.0" encoding="UTF-8"?>
<project xmlns="http://maven.apache.org/POM/4.0.0"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
<modelVersion>4.0.0</modelVersion>

<groupId>faas</groupId>
<artifactId>benchmark</artifactId>
<version>1</version>

<properties>
<maven.compiler.source>8</maven.compiler.source>
<maven.compiler.target>8</maven.compiler.target>
<project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
</properties>

<dependencies>
<!-- https://mvnrepository.com/artifact/com.google.code.gson/gson -->
<dependency>
<groupId>com.google.code.gson</groupId>
<artifactId>gson</artifactId>
<version>2.11.0</version>
</dependency>

</dependencies>
<build>
<plugins>
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-shade-plugin</artifactId>
<version>3.2.4</version>
<executions>
<execution>
<phase>package</phase>
<goals>
<goal>shade</goal>
</goals>
<configuration>
<createDependencyReducedPom>false</createDependencyReducedPom>
</configuration>
</execution>
</executions>
</plugin>
</plugins>
</build>
</project>
Original file line number Diff line number Diff line change
@@ -0,0 +1,119 @@
package faas;
import com.google.gson.*;
import utils.Order;
import utils.OrderItem;
import utils.OrderItemSet;

import java.util.ArrayList;
import java.util.List;
import java.util.Map;
import java.util.Map.Entry;
import java.util.Set;
import java.util.HashSet;
import java.util.HashMap;

public class App {


private static boolean trainingFinished = false;

public static final int MAX_NUMBER_OF_RECOMMENDATIONS = 10;



public static JsonObject handler(JsonObject args) {
Gson gson = new Gson();
JsonObject jsonResult = new JsonObject();
// Deserialize JSON input to Lists of OrderItem and Order
JsonArray orderItemsArray = args.getAsJsonArray("orderItems");
JsonArray ordersArray = args.getAsJsonArray("orders");

List<OrderItem> orderItems = new ArrayList<>();
for (JsonElement element : orderItemsArray) {
orderItems.add(gson.fromJson(element, OrderItem.class));
}

List<Order> orders = new ArrayList<>();
for (JsonElement element : ordersArray) {
orders.add(gson.fromJson(element, Order.class));
}
Map<Long, Map<Long, Double>> userBuyingMatrix;
Map<Long, Set<OrderItemSet>> userItemSets;
Set<Long> totalProducts;
long tic = System.currentTimeMillis();
totalProducts = new HashSet<>();
// first create order mapping unorderized
Map<Long, OrderItemSet> unOrderizeditemSets = new HashMap<>();
for (OrderItem orderItem : orderItems) {
if (!unOrderizeditemSets.containsKey(orderItem.getOrderId())) {
unOrderizeditemSets.put(orderItem.getOrderId(), new OrderItemSet());
unOrderizeditemSets.get(orderItem.getOrderId()).setOrderId(orderItem.getOrderId());
}
unOrderizeditemSets.get(orderItem.getOrderId()).getOrderset().put(orderItem.getProductId(),
orderItem.getQuantity());
// see, if we already have our item
if (!totalProducts.contains(orderItem.getProductId())) {
// if not known yet -> add
totalProducts.add(orderItem.getProductId());
}
}
// now map each id with the corresponding order
Map<Order, OrderItemSet> itemSets = new HashMap<>();
for (Long orderid : unOrderizeditemSets.keySet()) {
Order realOrder = findOrder(orders, orderid);
itemSets.put(realOrder, unOrderizeditemSets.get(orderid));
}
userItemSets = new HashMap<>();
for (Order order : itemSets.keySet()) {
if (!userItemSets.containsKey(order.getUserId())) {
userItemSets.put(order.getUserId(), new HashSet<OrderItemSet>());
}
itemSets.get(order).setUserId(order.getUserId());
userItemSets.get(order.getUserId()).add(itemSets.get(order));
}
userBuyingMatrix = createUserBuyingMatrix(userItemSets);
executePreprocessing();
trainingFinished = true;
jsonResult.addProperty("trainingFinished", trainingFinished);
return jsonResult;
}
protected static void executePreprocessing() {
// do nothing
}

private static Order findOrder(List<Order> orders, long orderid) {
for (Order order : orders) {
if (order.getId() == orderid) {
return order;
}
}
return null;
}

private static Map<Long, Map<Long, Double>> createUserBuyingMatrix(Map<Long, Set<OrderItemSet>> useritemsets) {
Map<Long, Map<Long, Double>> matrix = new HashMap<>();
// for each user
for (Map.Entry<Long, Set<OrderItemSet>> entry : useritemsets.entrySet()) {
// create a new line for this user-ID
Map<Long, Double> line = new HashMap<>();
// for all orders of that user
for (OrderItemSet orderset : entry.getValue()) {
// for all orderitems of that orderset
for (Entry<Long, Integer> product : orderset.getOrderset().entrySet()) {
// if key was not known before -> first occurence
if (!line.containsKey(product.getKey())) {
line.put(product.getKey(), Double.valueOf(product.getValue()));
} else {
// if key was known before -> increase counter
line.put(product.getKey(), Double.valueOf(line.get(product.getKey()) + product.getValue()));
}
}
}
// add this user-ID to the matrix
matrix.put(entry.getKey(), line);
}
return matrix;
}

}
//}
Original file line number Diff line number Diff line change
@@ -0,0 +1,293 @@
/**
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package utils;

/**
* Entity for orders.
*
* @author Joakim von Kistowski
*
*/
public class Order {

private long id;
private long userId;
private String time;

private long totalPriceInCents;
private String addressName;
private String address1;
private String address2;

private String creditCardCompany;
private String creditCardNumber;
private String creditCardExpiryDate;

/**
* Create a new and empty order.
*/
public Order() {

}

/**
* Every entity needs a copy constructor.
*
* @param order
* The order to copy.
*/
public Order(Order order) {
setId(order.getId());
setUserId(order.getUserId());
setTime(order.getTime());
setTotalPriceInCents(order.getTotalPriceInCents());
setAddressName(order.getAddressName());
setAddress1(order.getAddress1());
setAddress2(order.getAddress2());
setCreditCardCompany(order.getCreditCardCompany());
setCreditCardNumber(order.getCreditCardNumber());
setCreditCardExpiryDate(order.getCreditCardExpiryDate());
}

/**
* Get the id (remember that this ID may be incorrect, especially if a separate id was passed).
*
* @return The id.
*/
public long getId() {
return id;
}

/**
* For REST use only. Sets the ID. Ignored by persistence.
*
* @param id
* ID, as passed by the REST API.
*/
public void setId(long id) {
this.id = id;
}

/**
* Get the User id.
*
* @return the userId.
*/
public long getUserId() {
return userId;
}

/**
* Set the User Id.
*
* @param userId
* the userId to set.
*/
public void setUserId(long userId) {
this.userId = userId;
}

/**
* Get the time of order (ISO formatted). Formatted using {@link DateTimeFormatter.ISO_LOCAL_DATE_TIME}.
*
* @return the time.
*/
public String getTime() {
return time;
}

/**
* Set the time of order (ISO formatted). Format using {@link DateTimeFormatter.ISO_LOCAL_DATE_TIME}.
*
* @param time
* the time to set.
*/
public void setTime(String time) {
this.time = time;
}

/**
* Get the total price in cents.
*
* @return the totalPriceInCents.
*/
public long getTotalPriceInCents() {
return totalPriceInCents;
}

/**
* Set the total price in cents.
*
* @param totalPriceInCents
* the totalPriceInCents to set.
*/
public void setTotalPriceInCents(long totalPriceInCents) {
this.totalPriceInCents = totalPriceInCents;
}

/**
* Get the name for the address.
*
* @return the addressName.
*/
public String getAddressName() {
return addressName;
}

/**
* Set the name for the address.
*
* @param addressName
* the addressName to set.
*/
public void setAddressName(String addressName) {
this.addressName = addressName;
}

/**
* Get address line 1.
*
* @return the address1.
*/
public String getAddress1() {
return address1;
}

/**
* Set address line 1.
*
* @param address1
* the address1 to set.
*/
public void setAddress1(String address1) {
this.address1 = address1;
}

/**
* Get address line 2.
*
* @return the address2.
*/
public String getAddress2() {
return address2;
}

/**
* Set address line 2.
*
* @param address2
* the address2 to set.
*/
public void setAddress2(String address2) {
this.address2 = address2;
}

/**
* Get the name of the credit card company.
*
* @return the creditCardCompany.
*/
public String getCreditCardCompany() {
return creditCardCompany;
}

/**
* Set the name of the credit card company.
*
* @param creditCardCompany
* the creditCardCompany to set.
*/
public void setCreditCardCompany(String creditCardCompany) {
this.creditCardCompany = creditCardCompany;
}

/**
* Get the credit card number.
*
* @return the creditCardNumber.
*/
public String getCreditCardNumber() {
return creditCardNumber;
}

/**
* Set the credit card number.
*
* @param creditCardNumber
* the creditCardNumber to set.
*/
public void setCreditCardNumber(String creditCardNumber) {
this.creditCardNumber = creditCardNumber;
}

/**
* Get the credit card expiry date (ISO formatted). Formatted using {@link DateTimeFormatter.ISO_LOCAL_DATE}.
*
* @return the creditCardExpiryDate.
*/
public String getCreditCardExpiryDate() {
return creditCardExpiryDate;
}

/**
* Set the credit card expiry date (ISO formatted). Format using {@link DateTimeFormatter.ISO_LOCAL_DATE}.
*
* @param creditCardExpiryDate
* the creditCardExpiryDate to set.
*/
public void setCreditCardExpiryDate(String creditCardExpiryDate) {
this.creditCardExpiryDate = creditCardExpiryDate;
}

/*
* (non-Javadoc)
*
* @see java.lang.Object#hashCode()
*/
@Override
public int hashCode() {
final int prime = 31;
int result = 1;
result = prime * result + (int) (id ^ (id >>> 32));
result = prime * result + (int) (userId ^ (userId >>> 32));
return result;
}

/*
* (non-Javadoc)
*
* @see java.lang.Object#equals(java.lang.Object)
*/
@Override
public boolean equals(Object obj) {
if (this == obj) {
return true;
}
if (obj == null) {
return false;
}
if (getClass() != obj.getClass()) {
return false;
}
Order other = (Order) obj;
if (id != other.id) {
return false;
}
if (userId != other.userId) {
return false;
}
return true;
}

}
Original file line number Diff line number Diff line change
@@ -0,0 +1,180 @@
package utils;



/**
* Entity Class for OrderItems (item with quantity in shopping cart or order).
*
* @author Joakim von Kistowski
*
*/
public class OrderItem {

private long id;
private long productId;
private long orderId;
private int quantity;
private long unitPriceInCents;

/**
* Create a new and empty OrderItem.
*/
public OrderItem() {

}

/**
* Every Entity needs a Copy-Constructor!
*
* @param orderItem
* The entity to Copy.
*/
public OrderItem(OrderItem orderItem) {
setId(orderItem.getId());
setProductId(orderItem.getProductId());
setOrderId(orderItem.getOrderId());
setQuantity(orderItem.getQuantity());
setUnitPriceInCents(orderItem.getUnitPriceInCents());
}

/**
* Get the id (remember that this ID may be incorrect, especially if a separate id was passed).
*
* @return The id.
*/
public long getId() {
return id;
}

/**
* For REST use only. Sets the ID. Ignored by persistence.
*
* @param id
* ID, as passed by the REST API.
*/
public void setId(long id) {
this.id = id;
}

/**
* ID of the order item's product.
*
* @return Product Id;
*/
public long getProductId() {
return productId;
}

/**
* Sets the ID of the order item's product. Every order Item MUST have a valid product ID.
*
* @param productId
* The product ID to set.
*/
public void setProductId(long productId) {
this.productId = productId;
}

/**
* Get the quantity (amount in shopping cart/order).
*
* @return The quantity.
*/
public int getQuantity() {
return quantity;
}

/**
* Set the quantity (amount in shopping cart/order).
*
* @param quantity
* The quantity.
*/
public void setQuantity(int quantity) {
this.quantity = quantity;
}

/**
* The price per single item in the order item.
*
* @return Price per single item.
*/
public long getUnitPriceInCents() {
return unitPriceInCents;
}

/**
* Set the price per single item in the order item.
*
* @param unitPriceInCents
* Price per single item.
*/
public void setUnitPriceInCents(long unitPriceInCents) {
this.unitPriceInCents = unitPriceInCents;
}

/**
* Gets the ID of the order item's order.
*
* @return The order ID.
*/
public long getOrderId() {
return orderId;
}

/**
* Sets the ID of the order item's order. Persistence requires that every order item MUST have a valid order ID. For
* persistence the order must already exist in database.
*
* @param orderId
* The order ID to set.
*/
public void setOrderId(long orderId) {
this.orderId = orderId;
}

/*
* (non-Javadoc)
*
* @see java.lang.Object#hashCode()
*/
@Override
public int hashCode() {
final int prime = 31;
int result = 1;
result = prime * result + (int) (id ^ (id >>> 32));
result = prime * result + (int) (orderId ^ (orderId >>> 32));
result = prime * result + (int) (productId ^ (productId >>> 32));
return result;
}

/*
* (non-Javadoc)
*
* @see java.lang.Object#equals(java.lang.Object)
*/
@Override
public boolean equals(Object obj) {
if (this == obj) {
return true;
}
if (obj == null) {
return false;
}
if (getClass() != obj.getClass()) {
return false;
}
OrderItem other = (OrderItem) obj;
if (id != other.id) {
return false;
}
if (orderId != other.orderId) {
return false;
}
if (productId != other.productId) {
return false;
}
return true;
}

}
Original file line number Diff line number Diff line change
@@ -0,0 +1,80 @@
package utils;
import java.util.HashMap;
import java.util.Map;

/**
* Objects of this class holds a mapping of {@link Product} IDs to quantities
* that were bought in the same {@link Order} by one {@link User}. Non-present
* {@link Product} IDs imply a quantity of 0.
*
* @author Johannes Grohmann
*
*/
public class OrderItemSet {

/**
* Standard constructor.
*/
public OrderItemSet() {
orderset = new HashMap<>();
}

/**
* The user that made this order.
*/
private long userId;

/**
* The orderId that the Items were bought in.
*/
private long orderId;

/**
* The productIds that were bought together with the given quantity.
*/
private Map<Long, Integer> orderset;

/**
* @return the orderset
*/
public Map<Long, Integer> getOrderset() {
return orderset;
}

/**
* @param orderset
* the orderset to set
*/
public void setOrderset(Map<Long, Integer> orderset) {
this.orderset = orderset;
}

/**
* @return the orderId
*/
public long getOrderId() {
return orderId;
}

/**
* @param orderId
* the orderId to set
*/
public void setOrderId(long orderId) {
this.orderId = orderId;
}

/**
* @return the userId
*/
public long getUserId() {
return userId;
}

/**
* @param userId the userId to set
*/
public void setUserId(long userId) {
this.userId = userId;
}
}
62 changes: 62 additions & 0 deletions benchmarks/wrappers/openwhisk/java/Main.java
Original file line number Diff line number Diff line change
@@ -0,0 +1,62 @@
import faas.App;
import com.google.gson.Gson;
import com.google.gson.JsonObject;
import util.SessionBlob;
import util.ShaSecurityProvider;
import java.time.Instant;
import java.time.Duration;
import java.io.File;
import java.io.IOException;
//import jakarta.ws.rs.core.Response;


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();

long start_nano = System.nanoTime();

Instant begin = Instant.now();
JsonObject result = function.handler(args);
Instant end = Instant.now();

long end_nano = System.nanoTime();

// long computeTime = Duration.between(begin, end).toNanos() / 1000; // Convert nanoseconds to microseconds

long computeTime = end_nano - start_nano;
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();
jsonResult.addProperty("begin", formattedBegin);
jsonResult.addProperty("end", formattedEnd);
jsonResult.addProperty("request_id", requestId);
jsonResult.addProperty("compute_time", computeTime);
jsonResult.addProperty("is_cold", isCold);
jsonResult.addProperty("result", result.toString());
return jsonResult;
}

}
Empty file.
8 changes: 5 additions & 3 deletions config/example.json
Original file line number Diff line number Diff line change
@@ -1,12 +1,14 @@
{
"experiments": {
"deployment": "openwhisk",
"deployment": "aws",
"update_code": false,
"update_storage": false,
"download_results": false,
"architecture": "arm64",
"container_deployment": true,
"runtime": {
"language": "python",
"version": "3.7"
"version": "3.8"
},
"type": "invocation-overhead",
"perf-cost": {
@@ -89,4 +91,4 @@
}
}
}
}
}
20 changes: 19 additions & 1 deletion config/systems.json
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
{
"general": {
"docker_repository": "spcleth/serverless-benchmarks"
"docker_repository": ""
},
"local": {
"experiments": {
@@ -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"
}
}
}
}
}
8 changes: 8 additions & 0 deletions dockerfiles/openwhisk/java/Dockerfile.function
Original file line number Diff line number Diff line change
@@ -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
2 changes: 1 addition & 1 deletion sebs.py
Original file line number Diff line number Diff line change
@@ -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")
52 changes: 51 additions & 1 deletion sebs/benchmark.py
Original file line number Diff line number Diff line change
@@ -1,6 +1,7 @@
import glob
import hashlib
import json
import subprocess
import os
import shutil
import subprocess
@@ -200,8 +201,9 @@ def hash_directory(directory: str, deployment: str, language: str):
FILES = {
"python": ["*.py", "requirements.txt*"],
"nodejs": ["*.js", "package.json"],
"java": ["*.java", "pom.xml"],
}
WRAPPERS = {"python": "*.py", "nodejs": "*.js"}
WRAPPERS = {"python": "*.py", "nodejs": "*.js", "java": "*.java"}
NON_LANG_FILES = ["*.sh", "*.json"]
selected_files = FILES[language] + NON_LANG_FILES
for file_type in selected_files:
@@ -250,16 +252,51 @@ 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):
shutil.copy2(nodejs_package_json, os.path.join(output_dir, "package.json"))

#This is for making jar file and add it to docker directory
def add_java_output(self, code_dir):

if self.language_name == "java":

# Step 1: Move Main.java o src directory
src_dir = os.path.join(code_dir, "src", "main", "java")
if os.path.exists(code_dir):
main_java_path = os.path.join(code_dir, "Main.java")
if os.path.exists(main_java_path):
shutil.move(main_java_path, src_dir)

# Step 2: Run mvn clean install
try:
# Navigate to the code directory where the pom.xml file is located
subprocess.run(['mvn', 'clean', 'install'], cwd=code_dir, check=True, text=True, capture_output=True)
Copy link
Collaborator

Choose a reason for hiding this comment

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

Typically, we run install steps in a Docker container - see dockerfiles/{lang}/{platform}. We create a build image for each platform.

For OpenWhisk, we don't use build images because we have function images that we deploy. Then why do we run maven here? Shouldn't we run it as a part of building the function image?

print("Maven build successful!")
except subprocess.CalledProcessError as e:
print(f"Error during Maven build:\n{e.stdout}\n{e.stderr}")
return


def add_benchmark_data(self, output_dir):
cmd = "/bin/bash {benchmark_path}/init.sh {output_dir} false"
paths = [
@@ -288,6 +325,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 +366,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

@@ -497,6 +546,7 @@ def build(
self.copy_code(self._output_dir)
self.add_benchmark_data(self._output_dir)
self.add_deployment_files(self._output_dir)
self.add_java_output(self._output_dir)
self.add_deployment_package(self._output_dir)
self.install_dependencies(self._output_dir)
self._code_location, self._code_size = deployment_build_step(
3 changes: 2 additions & 1 deletion sebs/faas/function.py
Original file line number Diff line number Diff line change
@@ -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"])


77 changes: 44 additions & 33 deletions sebs/openwhisk/openwhisk.py
Original file line number Diff line number Diff line change
@@ -214,23 +214,27 @@ def package_code(
# to allow registration of function with OpenWhisk
self.build_base_image(directory, language_name, language_version, benchmark, is_cached)

# We deploy Minio config in code package since this depends on local
# deployment - it cannnot be a part of Docker image
CONFIG_FILES = {
"python": ["__main__.py"],
"nodejs": ["index.js"],
}
package_config = CONFIG_FILES[language_name]

benchmark_archive = os.path.join(directory, f"{benchmark}.zip")
subprocess.run(
["zip", benchmark_archive] + package_config, stdout=subprocess.DEVNULL, cwd=directory
)
self.logging.info(f"Created {benchmark_archive} archive")
bytes_size = os.path.getsize(benchmark_archive)
self.logging.info("Zip archive size {:2f} MB".format(bytes_size / 1024.0 / 1024.0))
return benchmark_archive, bytes_size

if language_name != 'java':
# We deploy Minio config in code package since this depends on local
# deployment - it cannnot be a part of Docker image
CONFIG_FILES = {
"python": ["__main__.py"],
"nodejs": ["index.js"],
}
package_config = CONFIG_FILES[language_name]

benchmark_archive = os.path.join(directory, f"{benchmark}.zip")
subprocess.run(
["zip", benchmark_archive] + package_config, stdout=subprocess.DEVNULL, cwd=directory
)
self.logging.info(f"Created {benchmark_archive} archive")
bytes_size = os.path.getsize(benchmark_archive)
self.logging.info("Zip archive size {:2f} MB".format(bytes_size / 1024.0 / 1024.0))
return benchmark_archive, bytes_size
benchmark_jar = os.path.join(directory, "docker", "target", "benchmark-1.jar")
bytes_size = os.path.getsize(benchmark_jar)

return benchmark_jar, bytes_size
def storage_arguments(self) -> List[str]:
storage = cast(Minio, self.get_storage())
return [
@@ -280,27 +284,34 @@ def create_function(self, code_package: Benchmark, func_name: str) -> "OpenWhisk
code_package.language_name,
code_package.language_version,
)

run_arguments = [
*self.get_wsk_cmd(),
"action",
"create",
func_name,
"--web",
"true",
"--docker",
docker_image,
"--memory",
str(code_package.benchmark_config.memory),
"--timeout",
str(code_package.benchmark_config.timeout * 1000),
*self.storage_arguments(),
code_package.code_location,
]
if code_package.language_name == 'java':
run_arguments.extend(["--main", "Main"])


subprocess.run(
[
*self.get_wsk_cmd(),
"action",
"create",
func_name,
"--web",
"true",
"--docker",
docker_image,
"--memory",
str(code_package.benchmark_config.memory),
"--timeout",
str(code_package.benchmark_config.timeout * 1000),
*self.storage_arguments(),
code_package.code_location,
],
run_arguments,
stderr=subprocess.PIPE,
stdout=subprocess.PIPE,
check=True,
)

function_cfg.docker_image = docker_image
res = OpenWhiskFunction(
func_name, code_package.benchmark, code_package.hash, function_cfg