Sunday, December 30, 2007

SLIME - How to Profile in Lisp

If you have worked on a fairly *BIG* project you must have heard people saying, "Let's profile it first." When I started lisp programming I was clueless about profiling a lisp code. This was fairly easy in other programming languages by the tools they provide; I knew how to profile C/C++ code with GCC compiler options but not for lisp.
Here I am going to explain how to profile lisp codes using SLIME.
Suppose you have a function:

(defun foo()
(format t "Hello foo"))

and you call it like:

(loop for n
from 1 to 1000
do(progn
(print n)
(foo)))

Now you have to find how much time foo has taken. Below are the steps for that:

  • Run the command: M-x slime-toggle-profile-fdefinition and hit enter. It will ask you the function name you want to profile. Enter the function name (foo in our case) you want to profile.
  • Now run the function; as in our example we will run the loop for getting more data.
  • To see the profile data use command M-x slime-profile-report. This will show the profiled data in the format below:
seconds consed calls sec/call name
-----------------------------------------------------
0.015 587,712 1,000 0.000015 FOO
-----------------------------------------------------
0.015 587,712 1,000 Total

estimated total profiling overhead: .002 seconds
overhead estimation parameters:
0.0s/call, 2.03e-6s total profiling, 9.36e-7s internal profiling

There is profiling options for packages. For more details you can refer to SLIME Manual.

Tuesday, September 11, 2007

SLIME Setup for Windows

If you are trying to setup SLIME in Windows it is fairly a simple job now.

I have used SBCL version 1.0.6 and XEmacs 21.4.20 in this example.

Following are the steps that you need to perform for a minimal setup of SLIME:

1. Download and install XEmacs.

2. Download and install SBCL in a directory, say C:\SBCL.

3. Download and unzip SLIME in a directory, say C:\SLIME. Make sure you have the directory names noted correctly.

4. Edit your init.el file and put the following lisp codes there:

(setq inferior-lisp-program "c:/sbcl/sbcl.exe")
(add-to-list 'load-path "c:/home/site/slime-2.0/")
(require 'slime)
(slime-setup)

This is it you sould have the SLIME working for you. :-)

Defvar and Defparameter

Defvar and defparameter does the same thing as defining a variable but the difference is that in case of defparameter you have to initialize the variable with a value but in case of defvar you can define the variable but you can initialize it later. There is a catch here if you try to use a variable by defining it using defvar without initializing it, it will evaluate to unbound variable, and the unbound-variable slot for that variable will be set.

Recursion and Bottom up design

In Lisp you can go from simple to very complex solutions. This is possible because of REPL. If you start with something simple and add on top of that simple design you will end up in a better program.



Recursion is a phenomenon in Lisp as it can be used extensively (but should be used judiciously). I was just developing something which required a permutation calculation. Now we know that basic permutation is defined in mathematics as:

P(n) = n! ..... (1)

And permutation of r things from a set of n things is defined as:

P(n)(r) = n! / (n – r)! ..... (2)



And we can expand (1) as:



P(n) = n.(n – 1).(n – 2) …2.1

= n. P( n – 1)



So the following function can be used in Lisp:



(defun permut (x)

( if ( not( eq x 0))

( * x ( permut ( - x 1)))

( block nil ( return 1))))



And from equation (2):



P(n)(r) = P(n)/P( n – r)



We can write this general function as:



(defun permut-n-r(n r)

(/ (permut n) (permut (- n r))))



Here we have used the bottom up approach by defining the easier “permut” function first then moving to the “permut-n-r”.

A useful macro

When you return a (multiple) value(s) from a Lisp function you use either use return-from or return macro. Now how about this, if you have a macro which will look like:



(defun foo()

(return “foo”))



This can be useful as we can do away with all the “block” statements. The macro that I use for this purpose is fairly simple:



(defmacro xreturn(x)

(block nil (return x)))

I know that it has one limitation that it does not return multiple values but that's fairly easy for any lisper to figure out right. ;-)

Please do not ask me about the naming convention I followed. Any feedback in this will be more than welcomed.