Copyright (C) 2000-2012 |
GNU Info (librep.info)Compilation TipsCompilation Tips ---------------- Here are some tips for making compiled code run fast(er): * Instead of using `while' loops to traverse lists, use `mapc' or tail recursion. For example you might code a function to scan a list using iteration through a `while' loop: (defun scan-list (lst elt) "Search the LST for an element similar to ELT. Return it if one is found." (catch 'return (while (consp lst) (when (equal (car lst) elt) (throw 'return elt)) (setq lst (cdr lst))))) As well as obscuring what is actually happening, this will probably be fairly slow to execute. A more elegant solution is to use tail-recursion: (defun scan-list (lst elt) (if (equal (car lst) elt) elt (scan-list (cdr lst) elt))) An alternative idiom is to map an anonymous function over the list using the `mapc' function: (defun scan-list (lst elt) (catch 'return (mapc (lambda (x) (when (equal x elt) (throw 'return elt))) lst) nil)) In fact, the compiler knows that calls to `mapc' with a constant lambda expression can be open-coded, so it will code the list traversal directly using the virtual machine stack. However, in most cases the execution time differences are likely to negligible. * In some cases the functions `member', `memq', `assoc', etc... can be used to search lists. Since these are primitives written in C they will probably execute several times faster than an equivalent Lisp function. So the above `scan-list' example can again be rewritten, this time as: (defun scan-list (lst elt) (car (member elt lst))) * All conditional structures are equivalent when compiled (they are all translated to `cond' statements), so use whichever is the easiest to understand. * A certain amount of constant folding is performed. If a function is known to be free of side effects, and all its arguments are constants, then it is evaluated at compile-time, and the result folded into the program in its place. For example (logor (lsh 1 6) x) ==> (logor 32 x) * Careful use of named constants (Note: Defining Variables) can increase the speed of some programs. For example, in the Lisp compiler itself all the opcode values (small integers) are defined as constants. It must be stressed that in some cases constants may _not_ be suitable; they may drastically increase the size of the compiled program (when the constants are `big' objects, i.e. long lists) or even introduce subtle bugs (since two references to the same constant may not be `eq' whereas two references to the same variable are always `eq'). * Many primitives have corresponding byte-code instructions; these primitives will be quicker to call than those that don't (and incur a normal function call). Currently, the functions which have byte-code instructions (apart from all the special forms) are: `cons', `car', `cdr', `rplaca', `rplacd', `nth', `nthcdr', `aset', `aref', `length', `eval', `+', `*', `/', `%', `mod', `lognot', `not', `logior', `logand', `logxor', `equal', `eq', `=', `/=', `>', `<', `>=', `<=', `1+', `1-', `-', `set', `lsh', `zerop', `null', `atom', `consp', `listp', `numberp', `stringp', `vectorp', `throw', `boundp', `symbolp', `get', `put', `signal', `return', `reverse', `nreverse', `assoc', `assq', `rassoc', `rassq', `last', `mapcar', `mapc', `member', `memq', `delete', `delq', `delete-if', `delete-if-not', `copy-sequence', `sequencep', `functionp', `special-form-p', `subrp', `eql', `max', `min', `filter', `macrop', `bytecodep', `bind-object'. * When a file is being compiled each top-level form it contains is inspected to see if it should be compiled into a byte-code form. Different types of form are processed in different ways: * Function and macro definitions have their body forms compiled into a single byte-code form. The doc-string and interactive declaration are not compiled. * If the form is a list form (Note: List Forms) and the symbol which is the car of the list is one of: `if', `cond', `when', `unless', `let', `let*', `catch', `unwind-protect', `error-protect', `with-buffer', `with-window', `progn', `prog1', `prog2', `while', `and', `or', `case'. then the form is compiled. Otherwise it is just written to the output file in its uncompiled state. If your program contains a lot of top-level forms which you know will not be compiled automatically, consider putting them in a `progn' block to make the compiler coalesce them into one byte-code form. automatically generated by info2www version 1.2.2.9 |