Skip to content

Instantly share code, notes, and snippets.

@mustafaakin
Created June 11, 2018 05:14
Show Gist options
  • Star 4 You must be signed in to star a gist
  • Fork 1 You must be signed in to fork a gist
  • Save mustafaakin/71e4494508311f7764e59b16e9dd3b8e to your computer and use it in GitHub Desktop.
Save mustafaakin/71e4494508311f7764e59b16e9dd3b8e to your computer and use it in GitHub Desktop.
package main
import (
"log"
"encoding/json"
"github.com/pkg/errors"
"github.com/aws/aws-lambda-go/lambda"
)
/*
#cgo CFLAGS: -I/usr/lib/jvm/java-8-openjdk-amd64/include
#cgo CFLAGS: -I/usr/lib/jvm/java-8-openjdk-amd64/include/linux
#include <jni.h>
#include <stdio.h>
#include <stdlib.h>
static const char* convert_to_cstring(JNIEnv *env, jstring javaString)
{
return (*env)->GetStringUTFChars(env, javaString, 0);
}
static jstring convert_to_jstring(JNIEnv *env, char* buf)
{
return (*env)->NewStringUTF(env, buf);
}
*/
import "C"
var (
javaResponse = make(chan string)
goRequest = make(chan string)
)
func communicateJava(input interface{}) (interface{}, error) {
inBytes, err := json.Marshal(input)
if err != nil {
return nil, err
}
inputStr := string(inBytes)
// Write to Go
log.Println("Recevied request")
goRequest <- inputStr
// Read from Java
respStr := <-javaResponse
var resp interface{}
err = json.Unmarshal([]byte(respStr), &resp)
if err != nil {
return nil, errors.WithStack(err)
}
return resp, nil
}
//export Java_Test_start
func Java_Test_start(env *C.JNIEnv, clazz C.jclass) {
log.SetPrefix("GO - ")
go func() {
lambda.Start(communicateJava)
}()
}
//export Java_Test_writeResponse
func Java_Test_writeResponse(env *C.JNIEnv, clazz C.jclass, input C.jstring) {
a := C.convert_to_cstring(env, input)
b := C.GoString(a)
javaResponse <- b
}
//export Java_Test_readRequest
func Java_Test_readRequest(env *C.JNIEnv, clazz C.jclass) C.jstring {
input := <-goRequest
cstr := C.CString(input)
cjstring := C.convert_to_jstring(env, cstr)
return cjstring
}
func main() {}
import org.apache.commons.lang3.time.StopWatch;
import org.apache.commons.math3.ml.clustering.CentroidCluster;
import org.apache.commons.math3.ml.clustering.Clusterable;
import org.apache.commons.math3.ml.clustering.DoublePoint;
import org.apache.commons.math3.ml.clustering.KMeansPlusPlusClusterer;
import org.apache.commons.math3.random.*;
import java.util.ArrayList;
import java.util.List;
import java.util.Random;
import java.util.stream.Collectors;
public class KMeans {
private int N = 100_000; // Number of points
private int K = 10; // Cluster centroids
private int seed = 5; // Seed for exact performance
private int D = 3; // Dimensions
public KMeansResult calculate() {
KMeansResult result = new KMeansResult();
StopWatch s = new StopWatch();
s.start();
// Initialize random generators and clusterer
Random random = new Random(seed);
RandomGenerator randomGenerator = RandomGeneratorFactory.createRandomGenerator(random);
RandomVectorGenerator generator = new UncorrelatedRandomVectorGenerator(D, new UniformRandomGenerator(randomGenerator));
KMeansPlusPlusClusterer<DoublePoint> kmeans = new KMeansPlusPlusClusterer<>(K);
kmeans.getRandomGenerator().setSeed(seed);
// Generate numbers
List<DoublePoint> pointList = new ArrayList<>();
for (int i = 0; i < N; i++) {
double[] doubles = generator.nextVector();
DoublePoint doublePoint = new DoublePoint(doubles);
pointList.add(doublePoint);
}
s.stop();
result.setGenerationMs(s.getTime());
s.reset();
// Do the actual clustering
s.start();
List<CentroidCluster<DoublePoint>> centers = kmeans.cluster(pointList);
List<Clusterable> collect = centers
.stream()
.map(CentroidCluster::getCenter)
.collect(Collectors.toList());
s.stop();
return result
.setTookMs(s.getTime())
.setCenters(collect);
}
public int getN() {
return N;
}
public KMeans setN(int n) {
N = n;
return this;
}
public int getK() {
return K;
}
public KMeans setK(int k) {
K = k;
return this;
}
public int getSeed() {
return seed;
}
public KMeans setSeed(int seed) {
this.seed = seed;
return this;
}
public int getD() {
return D;
}
public KMeans setD(int d) {
D = d;
return this;
}
}
import org.apache.commons.math3.ml.clustering.Clusterable;
import java.util.List;
class KMeansResult {
private List<Clusterable> centers;
private long tookMs;
private long generationMs;
public List<Clusterable> getCenters() {
return centers;
}
public KMeansResult setCenters(List<Clusterable> centers) {
this.centers = centers;
return this;
}
public long getTookMs() {
return tookMs;
}
public KMeansResult setTookMs(long tookMs) {
this.tookMs = tookMs;
return this;
}
public long getGenerationMs() {
return generationMs;
}
public KMeansResult setGenerationMs(long generationMs) {
this.generationMs = generationMs;
return this;
}
@Override
public String toString() {
return "MyKMeansResult{" +
"centers=" + centers +
", tookMs=" + tookMs +
", generationMs=" + generationMs +
'}';
}
}
import org.apache.log4j.Logger;
import org.json.JSONObject;
import org.json.JSONTokener;
import java.util.Date;
public class MyEntrypointJava {
private final static Logger logger = Logger.getLogger(Test.class);
public static native void start();
public static native void writeResponse(String input);
public static native String readRequest();
public static void main(String[] args) {
logger.info("Starting");
System.loadLibrary("Hello");
logger.info("Loaded Hello Golang lib, invoking Go for listening on Lambda Handler");
// Start lambda handler
start();
while (true) {
String request = readRequest();
logger.info("Java Received Request: " + request);
JSONTokener tokener = new JSONTokener(request);
JSONObject requestJSON = new JSONObject(tokener);
// After parsing the input, do the actual calculation
KMeans kMeans = new KMeans()
.setK(requestJSON.getInt("k"))
.setD(requestJSON.getInt("d"))
.setN(requestJSON.getInt("n"))
.setSeed(requestJSON.getInt("seed"));
logger.info("Calculating in Java");
KMeansResult myKMeansResult = kMeans.calculate();
// Prepare a response JSON Object for response
JSONObject responseJSON = new JSONObject()
.put("centers", myKMeansResult.getCenters())
.put("input-gen-duration", myKMeansResult.getGenerationMs())
.put("duration", myKMeansResult.getTookMs())
.put("date", new Date());
String response = responseJSON.toString();
writeResponse(response);
}
}
}
<?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>mustafa</groupId>
<artifactId>graalvm-java-go-awslambda</artifactId>
<version>1.0-SNAPSHOT</version>
<properties>
<maven.compiler.target>1.8</maven.compiler.target>
<maven.compiler.source>1.8</maven.compiler.source>
</properties>
<dependencies>
<dependency>
<groupId>org.json</groupId>
<artifactId>json</artifactId>
<version>20180130</version>
</dependency>
<dependency>
<groupId>org.apache.commons</groupId>
<artifactId>commons-math3</artifactId>
<version>3.6.1</version>
</dependency>
<dependency>
<groupId>org.apache.commons</groupId>
<artifactId>commons-lang3</artifactId>
<version>3.7</version>
</dependency>
<dependency>
<groupId>log4j</groupId>
<artifactId>log4j</artifactId>
<version>1.2.17</version>
</dependency>
<dependency>
<groupId>com.amazonaws</groupId>
<artifactId>aws-lambda-java-core</artifactId>
<version>1.1.0</version>
</dependency>
</dependencies>
<build>
<plugins>
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-shade-plugin</artifactId>
<version>2.4.3</version>
<executions>
<!-- Run shade goal on package phase -->
<execution>
<phase>package</phase>
<goals>
<goal>shade</goal>
</goals>
</execution>
</executions>
</plugin>
</plugins>
</build>
</project>
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment