Fork me on GitHub

hi. Tried to modify @yogthos’s http-kit web server example ( to run with immutant on graalvm. Would like to bench graal version against JVM, but not sure what needs to be changed for it to work. it compiles ok, but doesn’t start.


➜  graal-web-app-example git:(master) ✗ lein native-image
q[/Users/tommi/projects/ikitommi/graal-web-app-example/target/app:85064]    classlist:   9,258.24 ms
[/Users/tommi/projects/ikitommi/graal-web-app-example/target/app:85064]        (cap):   1,199.52 ms
[/Users/tommi/projects/ikitommi/graal-web-app-example/target/app:85064]        setup:   7,486.92 ms
18:10:39.094 [ForkJoinPool-2-worker-6] DEBUG org.jboss.logging - Logging Provider: org.jboss.logging.Slf4jLoggerProvider
[/Users/tommi/projects/ikitommi/graal-web-app-example/target/app:85064]   (typeflow):  55,673.33 ms
[/Users/tommi/projects/ikitommi/graal-web-app-example/target/app:85064]    (objects):  19,417.84 ms
[/Users/tommi/projects/ikitommi/graal-web-app-example/target/app:85064]   (features):   2,952.99 ms
[/Users/tommi/projects/ikitommi/graal-web-app-example/target/app:85064]     analysis:  94,427.92 ms
[/Users/tommi/projects/ikitommi/graal-web-app-example/target/app:85064]     (clinit):     455.46 ms
[/Users/tommi/projects/ikitommi/graal-web-app-example/target/app:85064]     universe:   6,509.92 ms
[/Users/tommi/projects/ikitommi/graal-web-app-example/target/app:85064]      (parse):   3,253.26 ms
[/Users/tommi/projects/ikitommi/graal-web-app-example/target/app:85064]     (inline):   2,902.17 ms
[/Users/tommi/projects/ikitommi/graal-web-app-example/target/app:85064]    (compile):  23,614.60 ms
[/Users/tommi/projects/ikitommi/graal-web-app-example/target/app:85064]      compile:  46,137.11 ms
[/Users/tommi/projects/ikitommi/graal-web-app-example/target/app:85064]        image:  29,207.83 ms
[/Users/tommi/projects/ikitommi/graal-web-app-example/target/app:85064]        write:   1,808.32 ms
[/Users/tommi/projects/ikitommi/graal-web-app-example/target/app:85064]      [total]: 230,092.99 ms
Created native image /Users/tommi/projects/ikitommi/graal-web-app-example/target/app
➜  graal-web-app-example git:(master) ✗ target/app
Exception in thread "main" java.lang.ClassNotFoundException: org.projectodd.wunderboss.web.Web$CreateOption
	at java.lang.Class.forName(
	at immutant.internal.options$opts__GT_map.invokeStatic(options.clj:73)
	at immutant.internal.options$opts__GT_map.invoke(options.clj:68)
	at immutant.internal.options$opts__GT_keywords.invokeStatic(options.clj:91)
	at immutant.internal.options$opts__GT_keywords.invoke(options.clj:87)
	at clojure.core$map$fn__5587.invoke(core.clj:2747)
	at clojure.lang.LazySeq.sval(
	at clojure.lang.LazySeq.seq(
	at clojure.lang.RT.seq(
	at clojure.core$seq__5124.invokeStatic(core.clj:137)
	at clojure.core$apply.invokeStatic(core.clj:652)
	at clojure.core$mapcat.invokeStatic(core.clj:2775)
	at clojure.core$mapcat.doInvoke(core.clj:2775)
	at clojure.lang.RestFn.invoke(
	at immutant.internal.options$opts__GT_set.invokeStatic(options.clj:96)
	at immutant.internal.options$opts__GT_set.doInvoke(options.clj:93)
	at clojure.lang.RestFn.invoke(
	at immutant.web.internal.wunderboss$server.invokeStatic(wunderboss.clj:48)
	at immutant.web.internal.wunderboss$server.invoke(wunderboss.clj:46)
	at immutant.web$run.invokeStatic(web.clj:110)
	at immutant.web$run.doInvoke(web.clj:23)
	at clojure.lang.RestFn.invoke(
	at server.core$_main.invokeStatic(core.clj:38)
	at server.core$_main.doInvoke(core.clj:33)
	at clojure.lang.RestFn.invoke(
	at clojure.lang.AFn.applyToHelper(
	at clojure.lang.RestFn.applyTo(
	at server.core.main(Unknown Source)


Is there a list of things that don’t work in Clojure & how to fix them? Immutant uses Class.forName for example (and that’s the one that fails).


one of the limitations is that you can't have any dynamic loading at runtime, so anything with reflection will throw errors


that is used in few places, should be easy to fix those. have a fork already.


(credits to @taylor)

🙂 4

in terms of benchmarks I think you can expect the following:


- startup time will be faster - long running processes will be slower (due to the absence of JIT)


clj-kondo is sometimes 2x slower natively than when ran with a JVM (e.g linting an entire project with all dependencies: 40s vs 20s)

😮 4

cool, thanks all, recompiling with the reflection-settings now.


still some work to do:

Warning: Aborting stand-alone image build. Detected a direct/mapped ByteBuffer in the image heap. A direct ByteBuffer has a pointer to unmanaged C memory, and C memory from the image generator is not available at image run time. A mapped ByteBuffer references a file descriptor, which is no longer open and mapped at run time. The object was probably created by a class initializer and is reachable from a static field. By default, all class initialization is done during native image building.You can manually delay class initialization to image run time by using the option -H:ClassInitialization=<class-name>. Or you can write your own initialization methods and call them explicitly from your main entry point.


idea was to push a graal-server entry to techempower to get solid comparsion of jvm-clojure & graal-clojure (json, plain-text, db). expect graal to be much slower, but good still.


@borkdude the other important metric is memory use, with my test graal version took only 4.4 megs, while running as uberjar weighed in at around a 100


Not sure how to get the Immutant running with graalvm. The reflection hints helped to get further, but the ByteBuffers seem troublesome. Getting errors of both eagerly & lazily compiling those via native-image options. I guess this needs to be done just once thou...


I remember a similar error when I tried to compile some database-related stuff (SQLite, lmdb, etc).


it never worked for me


here’s the repo, if someone has mad skills in configuring graal: . it seems including & excluding classes from build-time one-by-one might work, eventually (or not)


seems to be a common thing, micronaut (java) has at least --initialize-at-build-time=ch.qos.logback,com.fasterxml.jackson,fresh.graal,io.micronaut,io.netty,io.reactivex,org.reactivestreams,org.slf4j,org.yaml.snakeyaml,javax