The performance difference between Clojure and the pure Java implementations was much smaller than I'd thought. Quite amazing for a dynamically typed language to get so close to Java in performance, to be honest.
The ring-clojure performance was much lower than the Java equivalent, but that's expected because de-serialization can be A LOT faster when you use static types for guiding parsing (e.g. cache the string keys and never allocate object keys, maybe small values that are common as well). I wonder if Clojure contracts could be used for the same tricks.