How ’bout that start-up time?

How long does Clojure start-up really take? Let’s find out.

Get yourself a Clojure project. Download the dependencies and pre-generate the classpath:

lein deps
lein classpath > cp.txt

This lets us run “raw” Clojure, without any tooling. Assuming a Bash-like shell:

time java -cp "$(cat cp.txt)" clojure.main -e '(System/exit 0)'

Now add Leiningen:

time lein run -m clojure.main -e '(System/exit 0)'

Next, add the Leiningen REPL:

time lein repl <<< "(exit)"

If you’re a fan of Emacs and CIDER, start Emacs and paste this into a scratch buffer:

(require 'cider)

(defvar cider-jack-in-start-time nil)

(defun start-timing-cider-jack-in (&rest args)
  (setq cider-jack-in-start-time (current-time)))

(defun elapsed-time-cider-jack-in (&rest args)
  (when cider-jack-in-start-time
    (prog1 (format "%.3f seconds"
                   (float-time
                    (time-since cider-jack-in-start-time)))
      (setq cider-jack-in-start-time nil))))

(add-function :before
              (symbol-function 'cider-jack-in)
              #'start-timing-cider-jack-in)
(setq cider-connection-message-fn
      #'elapsed-time-cider-jack-in)

Evaluate that Elisp code with M-x eval-buffer, then open up your project.clj and run cider-jack-in.

Run each of these examples a few times to warm up the circuits.

How long does it take? On an empty project with just Clojure 1.8, I get:

java -cp … clojure.main 0.8 seconds
lein run -m clojure.main 2.2 seconds
lein repl 4.2 seconds
cider-jack-in 11.5 seconds

Yes, Clojure start-up could be faster, but make sure you know where the time is really going.

My environment: Leiningen 2.7.1, Oracle JDK 1.8.0_92, OS X

3 thoughts on “How ’bout that start-up time?”

  1. That cleared up some misconceptions and was actually quite enlightening for me. Thank you.

  2. I really do not care much about startup time: Its a single cost at the beginning when starting the environment.

    On a Raspberry PI (my home development environment) cider-jack-in-clojurescript takes slightly less than 3 minutes (using the standard ClojureScript, nothing self-hosted for now).

    As I am at home, I use the time to get a beer, the delay works as the perfect excuse.

  3. Yes! I went to a fair amount of work building a Clojurescript/Javascript command line “filter” because I figured the JVM couldn’t possibly start Clojure fast enough to be used as a “filter” at the command line. Then, after my wife (who works on the JVM) suggested ways to improve the Java/Clojure startup, I tried harder. Ultimately I built a Clojure uberjar which includes non-trivial code that will start up and run in the JVM in under 1 second on a reasonable machine. Building the uberjar requires AOT-ing the code, and installing it requires some Java magic that takes a script the first time you use it. But after that, it runs as a unix “filter” and will start up and run in less than one second. Anyone could do this. See https://github.com/kkinnear/zprint/blob/master/doc/filter.md for the full story (including comparative performance measurements) — including how you could do this yourself.

Comments are closed.