Wednesday, January 8, 2014

For some reason, starting Clojure is comically slow on my machine. Most people talk about a few seconds, but for me it's more like a minute from 'lein repl' to a usable state.

This is annoying. I need a good reason to restart my repls, and I usually make a cup of tea while it's happening.

Sometimes I come back and find that the thing has failed to start because the start up time has exceeded leiningen's built in time-out and been killed. The reasons this can happen are many and varied, I have found.

This is not the JVM's fault. A trivial java hello world program runs quickly enough that you can't tell that there is a startup time.

One way to speed it up is to get leiningen out of the loop and start clojure as a JVM program, but leiningen is a great classpath manager.

But you can have the best of both worlds:

$ lein classpath > LEIN_CLASSPATH

Gets the classpath and puts it in a file. You only need to do this when you change your project.clj file to add a new dependency.

$ LEIN_CLASSPATH=`cat LEIN_CLASSPATH`

Reads that file into an environment variable.

$ rlwrap java -classpath $LEIN_CLASSPATH clojure.main

Starts clojure with the right classpath. As a bonus, you can use rlwrap to be your command line editor, which works like the bash shell, and is much better than the default.

Which starts up an nrepl on port 4001, ready to be bound to from emacs, makes sure the jvm's in server mode, and gives it 800M maximum memory. It will only expand to that size if it needs it, so why not?

In either case clojure will execute a file called user.clj on the classpath, so you've got somewhere to put custom startup code if you like.

If I was feeling really clever, I might turn these commands into a script which remade the file if it was older than project.clj, etc. But these lines are always in my command line history, and that's actually good enough that I don't feel the need (yet).