Re: Generating code which compiles to a jmphash
- From: Gene <gene.ressler@xxxxxxxxx>
- Date: Mon, 24 Mar 2008 18:07:39 -0700 (PDT)
On Mar 24, 7:20 pm, fvmarcol...@xxxxxxxxx wrote:
Hi,
I have a number of small utility functions which I would like to
compile
to JMPHASHs (to steal a term from clisp's (disassemble 'foo) output.
Feel free to correct my terminology.) These functions are called
several million times. I can and have transformed small, clear
functions
into ugly, hard to maintain case statements.
A little background: I'm coding a puzzle solver in my spare time,
for the challenge and as a way to learn lisp. One part of the solver
is an end-game hash, which takes quite a while to compute.
Turning nice code into ugly code has made the code significantly
faster.
A simple response of "learn to write macros" probably would not
be inappropriate. On the other hand, I am at least starting to see
patterns in the code which I know can be abstracted away with macros,
and I'm hoping that a little shove in the right direction will make
that easier.
At the risk of too much information, I'll provide two examples.
Feel free to ignore the first one in your responses. The first
is included as better example of the kind of transformation
I am interested in, but the second is fairly trivial, and a good
jumping off point for me.
(defconstant dirs '(up down left right))
(defun all-moves ()
(loop for dir in dirs
append
(loop for i from 0 to 4
collect (list i dir))))
(defun move-to-int (move)
(+ (first move) (* 5 (position (second move) dirs))))
(nth 12 (all-moves))=> (2 left)
(map 'list 'move-to-int (all-moves))
=> (0 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19)
On Mar 24, 7:41 pm, fvmarcol...@xxxxxxxxx wrote:
Oops. I accidentially hit send before completing that post...
The problem with the above code is the function move-to-int.
Instead of calling (position ...) every time, I would like code
which compiles to a jmphash, as if I wrote it using case statements.
Here is the second example.
(defun old-char+ (char)
(if (char= char #\9)
#\A
(int-char (1+ (char-int char)))))
vs
(defun char+ (char)
(case char
(#\1 #\2) (#\2 #\3) (#\3 #\4) (#\4 #\5) (#\5 #\6) (#\6 #\7)
(#\7 #\8) (#\8 #\9) (#\9 #\A) (#\A #\B) (#\B #\C) (#\C #\D)
(#\D #\E) (#\E #\F) (#\F #\G) (#\G #\H) (#\H #\I) (t #\*)))
char+ results in a modest 5% improvement in code speed over old-char+.
I really don't care so much about that, or about finding the best
version of char+, but am interested in how you would write code
which given some range of inputs will compile to something similar
to the compiled code for char+.
Thanks. Sorry for the split post.
The 5% difference isn't surprising. Unless the compiler is very
clever, it is going to expand the case into an "if then else" chain
that is not going to run much faster than the (position ) call.
As the lists of values get long, hash tables will eventually be
faster. You can do something like:
CL-USER> (defun hashify (fn domain &key (test #'eql))
(let ((hash (make-hash-table :test test)))
(dolist (val domain hash)
(setf (gethash val hash) (funcall fn val)))))
CL-USER> (defun old-char+ (char)
(if (char= char #\9)
#\A
(code-char (1+ (char-code char)))))
CL-USER> (setq h (hashify #'old-char+ '(#\1 #\2 #\3 #\4 #\5 #\6 #\7 #
\8 #\9
#\A #\B #\C #\D #\E #\F #\G #\H #\I)))/
CL-USER> (gethash #\1 h)
#\2
T
If you are really hard-over on the case idea, then
CL-USER> (defmacro casify (fn domain case-key)
`(case ,case-key
,@(mapcar #'(lambda (x) (list x (funcall fn x)))
domain)))
CASIFY
CL-USER> (macroexpand-1 '(casify 1+ (1 2 3) foo))
(CASE FOO (1 2) (2 3) (3 4))
T
.
- Follow-Ups:
- Re: Generating code which compiles to a jmphash
- From: fvmarcoline
- Re: Generating code which compiles to a jmphash
- References:
- Generating code which compiles to a jmphash
- From: fvmarcoline
- Generating code which compiles to a jmphash
- Prev by Date: Re: advice for a Lisp newbie
- Next by Date: Re: Lexical contexts; or, Lambda, the Ultimate Module?
- Previous by thread: Re: Generating code which compiles to a jmphash
- Next by thread: Re: Generating code which compiles to a jmphash
- Index(es):
Relevant Pages
|