Share your thoughts in the 2024 State of Clojure Survey!

Welcome! Please see the About page for a little more info on how this works.

0 votes
in Printing by
Run this example code:

;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
(in-ns 'clojure.pprint)


(println "Basic output using raw str.")
(time
 (doseq [i (range 1000)]
   (apply str (interpose "," [1 2 3]))))


(println "Test 1 - raw cl-format")
(time
 (doseq [i (range 1000)]
   (clojure.pprint/cl-format nil "~{~D~^,~}" [1 2 3])))
;; ==> "Elapsed time: 231.345 msecs"


(println "Test 2 - call on the compiled format")
(def myx
  (compile-format  "~{~D~^,~}"))

(time
 (doseq [i (range 1000)]
   (clojure.pprint/cl-format nil myx [1 2 3])))



(println "Test 3 - using a formatter")
(def myy
  (formatter  "~{~D~^,~}"))

(time
 (doseq [i (range 1000)]
   (myy nil myx [1 2 3])))



(time
 (dotimes (i 100000)
   (format nil  "~{~D~^,~}" '(1 2 3))))

;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;

It will print something like this:

Basic output using raw str.
"Elapsed time: 2.402 msecs"
Test 1 - raw cl-format
"Elapsed time: 194.405 msecs"
Test 2 - call on the compiled format
"Elapsed time: 87.271 msecs"
Test 3 - using a formatter
"Elapsed time: 199.318 msecs"

So raw `str' is ~ 100X faster.

For reference, on the same hardware, using
SBCL Common Lisp, this test runs in < 1 ms.


There are (at least) 2 problems here:

 1. cl-format function begins with a line like:

    let [compiled-format (if (string? format-in) (compile-format format-in) format-in)

   But there is no api to pass in a compiled-format into it; (as compile-format
   is a private function, so can't be used at large) so this is kind of useless.

 2. Even using a precompiled formatter is way too slow.


Suggested fix: none, except perhaps warning unwary users that this
function is simply not suitable for tight loops, and should only be
used to pretty print user input strings, etc.

Thank you

2 Answers

0 votes
by
Reference: https://clojure.atlassian.net/browse/CLJ-1950 (reported by alex+import)
0 votes
by

It seems like this problem could be addressed in part by making compile-format public. The docstring for compile-format suggests using it as a way to improve performance; passing the compiled blob it returns to cl-format (in place of a format string) seems to work as expected. Perhaps it was just an oversight that the function is marked private?

by
compile-format helps but doesn't get anywhere close to e.g. clojure.core/format.

The lack of parity with common lisp's format was central to this thread:

https://www.reddit.com/r/lisp/comments/qho92i/a_casual_clojure_common_lisp_codeperformance/

cl-format needs to be rewritten eliminate a lot of performance that's left on the floor; particularly exclusive use of persistent structures where common lisp's format is not.  I started digging into it around the time of writing, but didn't get very far.
...