I recently used AllegroCL's profiler to learn why AllegroCL has done so poorly on the print benchmark. I found that AllegroCL is unusually slow when using FORMAT to print strings and numbers.
When I first designed hyperobject I assumed that it was faster to use a single FORMAT call with multiple values being printed at once rather than issuing sequential write commands. However, this is not true if writing the individual components can be made much faster than FORMAT's writing of individual components.
After some preliminary benchmarks with AllegroCL showing a 30x speed increase in writing short string using WRITE-STRING rather than FORMAT "~A", I reworked hyperobject's object display. Now, rather than caching a large format string and creating a function that returns the data values of all of the fields of an object, the program now compiles a series of commands to print the individual components (along with the usual formatting, labeling, and hyperlink elements).
Even though my typical object display has moved from a single (long) format command to dozens of write invocations, I've nearly tripled the speed of the printing in AllegroCL. Speed increases for other implementations range from 5-41%.
| Impl | Old Time (user/total) | New Time (user/total) | Increase |
|---|---|---|---|
| AllegroCL 6.2 | 8.2/8.3 | 2.9/3.0 | 183% |
| CMUCL 18e+ | 2.2/2.3 | 2.1/2.2 | 5% |
| Lispworks 4.2 | 5.8/6 | 4.1/4 | 41% |
| SBCL 0.8alpha.0.26 | 2.8/3.0 | 2.5/2.5 | 12% |
| SBCL-MT 0.8alpha.0.14 | 2.7/3.2 | 2.5/2.7 | 8% |
| SCL 1.1.1 | 5.1/5.5 | 4.6/4.8 | 11% |

Comments (6)
Have you looked at fast-format in cl-http?
It's a macro that parses the format string and replace the format call by equivalent write-string, print, etc. It only supports the most basic format directives but it's interesting.
Posted by Marc Battyani | May 14, 2003 8:12 AM
Posted on May 14, 2003 08:12
Thanks for the tip, Marc. I'll look at fast-format.
Besides the speed increase, I'm happy with the new design. While using FORMAT made my overall code smaller, in the print routines and I had to retrieve an object's format string and as well as a function that returns the processed values for the objects slots.
With the new design, the print routines now only need to retrieve a compiled function for that view object which prints the hyperobject.
Still, the benchmarks show that fast-format could be helpful on Allegro and Lispworks. CMUCL and SBCL appear to already have a fast format command.
Posted by Kevin Rosenberg | May 14, 2003 10:06 AM
Posted on May 14, 2003 10:06
Have you also taken a look at the standard Common Lisp macro FORMATTER ? As a long-time format user, I just found out about this macro recently. It looks like a hook for getting to more efficient formatted output.
(formatter control-string)
Returns a function which has behavior equivalent to:
#'(lambda (*standard-output* &rest arguments)
(apply #'format t control-string arguments)
arguments-tail)
where arguments-tail is either the tail of arguments which has as its car the argument that would be processed next if there were more format directives in the control-string, or else nil if no more arguments follow the most recently processed argument.
Posted by Tom Russ | June 3, 2003 11:33 AM
Posted on June 3, 2003 11:33
Following up my own comment. I just did an experiment with ACL 5.0.1 and didn't really notice any difference using formatter versus format.
Posted by Tom Russ | June 3, 2003 11:41 AM
Posted on June 3, 2003 11:41
In Allegro, FORMATTER apparently just produces a closure that calls the internal routine for FORMAT with the format and the rest of the arguments. I don't know if it preparses the format string as FORMAT does when SPEED > SPACE.
Posted by Paul Dietz | July 13, 2003 9:46 AM
Posted on July 13, 2003 09:46
Talking to Franz, I believe FORMATTER does preparse the format string. However, I'm quite happy now avoiding format and using lower-level stream writers for performance critical sections.
Posted by Kevin Rosenberg | July 13, 2003 12:08 PM
Posted on July 13, 2003 12:08