Fork me on GitHub
Adam Helins09:09:30

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


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

Adam Helins09:09:55

I guess the setup must be a lot easier as well


(Unrelated) Released dynaload 0.2.2 which gives better results than dynamic require in GraalVM binaries:


@adam678 Check out for getting started with Clojure + GraalVM native-image:

💯 6

Using a native shared library from Python: Thanks @sogaiu for the docs.

🙂 3

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

    public Object invoke() {
        return invokeStatic();


Alex Miller (Clojure team)12:09:52

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

Alex Miller (Clojure team)12:09:04

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


@borkdude may be you are familiar with this post already, but it touches on the "lie" bit iirc:

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

Adam 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


@adam678 I can get hello world down to 8MB


This is with 20.2.0 Java 11


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

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

Adam Helins15:09:12

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


FWIW, babashka can do all that too


direct linking also helps for binary size

Adam 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


that's the idea of bb yes

Adam 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?


@adam678 yes, your binary and memory usage during compilation can spike significantly if you don't do that.