Fork me on GitHub
#graalvm
<
2020-09-18
>
Helins09:09:30

I was curious about collecting your experiences in using graal + clj for AWS lambdas as opposed to cljs

borkdude09:09:48

@adam678 There are some people running babashka on AWS Lambda because of the fast startup, that is one example of a GraalVM binary

Helins09:09:55

I guess the setup must be a lot easier as well

borkdude09:09:57

(Unrelated) Released dynaload 0.2.2 which gives better results than dynamic require in GraalVM binaries: https://github.com/borkdude/dynaload

borkdude09:09:55

@adam678 Check out for getting started with Clojure + GraalVM native-image: https://github.com/lread/clj-graal-docs

💯 6
borkdude10:09:57

Using a native shared library from Python: https://github.com/borkdude/sci/blob/master/doc/libsci.md#using-libsci-from-python Thanks @sogaiu for the docs.

🙂 3
borkdude11:09:49

Nice tool for inspecting bytecode differences between 1.10.1 and 1.10.2-alpha wrt CLJ-1472:

$ clj -Sdeps '{:deps {org.clojure/clojure {:mvn/version "1.10.2-alpha1"} com.clojure-goes-fast/clj-java-decompiler {:mvn/version "0.3.0"}}}'
user=> (require 'clj-java-decompiler.core)
nil
user=> (clj-java-decompiler.core/decompile (locking (Object.) (+ 1 2 3)))

// Decompiling class: user$fn__192
import clojure.lang.*;

public final class user$fn__192 extends AFunction
{
    public static Object invokeStatic() {
        final Object lockee__5717__auto__195 = new Object();
        final Number num;
        synchronized (lockee__5717__auto__195) {
            num = Numbers.num(Numbers.add(Numbers.add(1L, 2L), 3L));
        }
        return num;
    }

    @Override
    public Object invoke() {
        return invokeStatic();
    }
}

nil

alexmiller12:09:52

Just keep in mind this is a lie, perhaps a helpful lie, but still a lie

alexmiller12:09:04

If you actually want to inspect bytecode differences you actually have to look at the bytecode

sogaiu12:09:48

@borkdude may be you are familiar with this post already, but it touches on the "lie" bit iirc: http://clojure-goes-fast.com/blog/introspection-tools-java-decompilers/

Helins14:09:58

All right, after experimenting a few hours and ironing out a few wrinkles, it turns out it is pretty easy using native-image for aws lambdas.

Helins14:09:56

For a simple "hello $name" example, image size is 30mb and memory usage ~50mb. Not particularly lightweight in that regard, but execution duration is 1 ms

borkdude14:09:21

@adam678 I can get hello world down to 8MB

borkdude14:09:26

This is with 20.2.0 Java 11

borkdude14:09:54

@adam678 Note that you can control memory usage with the usual JVM flags -Xmx etc, passed to the binary

Helins15:09:04

@borkdude But here, the app also acts as a simple custom lambda runtime, so it needs to issue http requests and parse json (ie. add jsonista and clj-http-light to deps), even for a hello world kind of demo. That explains the image size. Memory usage still seems high for a couple of very simple http request, but I haven't played with -Xmx and I am not sure how truly big it is in the context of a native image.

Helins15:09:12

(Yes, using 20.2.0-r11 (thanks to your reflector fix plugin, well done 👏))

borkdude15:09:07

FWIW, babashka can do all that too

borkdude15:09:25

direct linking also helps for binary size

Helins15:09:28

I will need to handle more complex use cases, but I wonder if babashka would help to keep things tight for those simpler ones, with the additional benefit that it wouldn't require long compilation time nor bothering with creating a runtime per app

borkdude15:09:24

that's the idea of bb yes

Helins15:09:37

In this simple example direct linking changes virtually nothing regarding the size, I guess it would make more of an impact if the deps were more clojury. But anyway, shouldn't direct linking be the default for native images? Is there any benefit not to do so?

borkdude15:09:45

@adam678 yes, your binary and memory usage during compilation can spike significantly if you don't do that. https://epiccastle.io/blog/faster-graalvm-clojure-compilation-times/