graalvm

Discuss GraalVM related topics. Use clojure 1.10.2 or newer for all new projects. Contribute to https://github.com/clj-easy/graal-docs and https://github.com/BrunoBonacci/graalvm-clojure. GraalVM slack: https://www.graalvm.org/slack-invitation/.
Helins 2020-09-18T09:05:30.001300Z

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

borkdude 2020-09-18T09:06:48.001800Z

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

Helins 2020-09-18T09:07:55.002500Z

I guess the setup must be a lot easier as well

borkdude 2020-09-18T09:08:57.003200Z

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

borkdude 2020-09-18T09:21:55.004Z

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

💯 2
borkdude 2020-09-18T10:39:57.004900Z

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.

🙂 1
borkdude 2020-09-18T11:18:49.005900Z

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

alexmiller 2020-09-18T12:44:52.007100Z

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

alexmiller 2020-09-18T12:46:04.008300Z

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

2020-09-18T12:48:48.008900Z

@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/

borkdude 2020-09-18T12:53:32.009100Z

thanks

Helins 2020-09-18T14:21:58.010300Z

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.

Helins 2020-09-18T14:23:56.012Z

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

borkdude 2020-09-18T14:29:21.012400Z

@adam678 I can get hello world down to 8MB

borkdude 2020-09-18T14:30:26.013Z

This is with 20.2.0 Java 11

borkdude 2020-09-18T14:32:54.013500Z

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

Helins 2020-09-18T15:36:04.017200Z

@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.

Helins 2020-09-18T15:38:12.018100Z

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

borkdude 2020-09-18T15:39:07.018400Z

FWIW, babashka can do all that too

borkdude 2020-09-18T15:39:25.018600Z

direct linking also helps for binary size

Helins 2020-09-18T15:44:28.020700Z

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

borkdude 2020-09-18T15:45:24.020900Z

that's the idea of bb yes

Helins 2020-09-18T15:51:37.023100Z

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?

borkdude 2020-09-18T15:55:45.023800Z

@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/

borkdude 2020-09-18T18:00:35.024200Z

A tip regarding http-kit and graalvm: https://github.com/http-kit/http-kit/issues/447