Compiling
E N D
Presentation Transcript
Compiling “premature optimization is the root of all evil.” -Donald Knuth
Optimization • In LISP, you can write slow code fast or fast code slow • Experience will help you overcome common pitfalls (over use of append in recursive algorithms for example) • In general, worry about the top level algorithms first. You can always speed it up later
Compiling • LISP can be compiled into machine code just like other languages • Typically results in a drastic speed up for LISP programs • Compilation can reduce both running time and memory consumption
Time a Function • You can see how long it takes to evaluate a function by wrapping the function call in a call to time (defun waste-time (n) (dotimes (i n) (* i i))) >(time (waste-time 50000)) real time : 0.020 secs run-gbc time : 0.020 secs child run time : 0.000 secs gbc time : 0.000 secs NIL
Compile >(time (waste-time 50000000)) real time : 21.690 secs run-gbc time : 20.770 secs child run time : 0.000 secs gbc time : 0.870 secs NIL >(compile 'waste-time) […Compiler output…] >(time (waste-time 50000000)) real time : 11.220 secs run-gbc time : 10.200 secs child run time : 0.000 secs gbc time : 0.950 secs NIL
Disassemble • We can look at the assembly code produced by compile using disassemble • System and implementation dependent • Here’s an example in CLISP >(defun add1 (n) (1+ n)) ADD1 >(disassemble 'add1) Disassembly of function ADD1 1 required argument 0 optional arguments No rest parameter No keyword parameters 3 byte-code instructions: 0 (LOAD&PUSH 1) 1 (CALLS2 151) ; 1+ 3 (SKIP&RET 2) NIL • GCL output can be a mess since it actually transforms LISP into C code
Compile-File • You can also compile all functions in a given file (compile-file "file.lisp") • To run functions from the compiled file, load it like any other file (load "file.fas") • The specific file extension depends on implementation
Inlining • You can make a function be an inline function by using declare (defun f (x) (* x x)) (defun g (x) (declare (inline f)) (+ (f x) (f x))) • Now, upon compiling g, the actual body of f will be copied into g in the pertinent locations, though only within g. • To make f be an inline function everywhere, use declaim instead of declare, within the global scope. • Cannot be used with recursive functions
More Type Safety • declare and declaim can specify other compiler directives • You can use to streamline compiled functions to only expect certain types using type >(defun f (x y) (declare (type integer x y)) (+ x y)) F >(f 5.6 3.4) 9.0 >(compile 'f) …Compiler output… >(f 3 4) 7 >(f 5.6 3.4) Error
Optimizing • The optimize declaration allows several optimization priorities to be set • Priorities are on a scale from 0 to 3, with 3 the most important • compilation-speed: speed of the compilation process • debug: ease of debugging • safety: run-time error checking • space: both code size and run-time space • speed: speed of the object code • Example specification (defun f (x y) (declare (optimize (safety 2) (speed 3))) (+ x y))