1. Use sbcl profiler:
)lisp (sb-sprof:start-profiling)
-- do the computation
)lisp (sb-sprof:stop-profiling)
)lisp (sb-report)
There is some effort involved in reading reports and some part
may be misleading, but usully it helps a lot.
2. Boot flag '$reportOptimization' causes intepreter to print
generated Lisp code. Set it like
)boot $reportOptimization := true
and do your computation.
3. Interpreter frequently inserts runtime coercions. In such
case getting better type agreement or writing in Spad can help.
4. In HyperDoc you can find wich implementation is in use. Search
for List, give Integer as parameter, click on 'Operations', choose
'removeDuplicates!', click on 'Implementations'. It tells you
that 'removeDuplicates!' is implemented in List. Looking at code
in List shows quadratic loop. This is generic implementation,
without extra structure is to not possible to do better.
5. For mass removal of duplicates hash tables should be better.
You can try something like:
f2(n:INT):INT ==
t := empty()$Table(INT, Boolean)
for x in -n..n repeat
for y in -n..n | y >= x repeat
setelt!(t, x*x+x*y+y*y, true)
%keys(t)
You can also try 'XHashTable(INT, Boolean)' instead of 'Table'
(for Integer keys 'Table' probably is faster, but 'XHashTable'
can give you hash table in some cases where 'Table' gives
association list).
> ---
>
> f1(n:INT):INT ==
> #removeDuplicates!(concat! [[x*x+x*y+y*y for x in -n..n|x<=y] for y in
> -n..n])
>
> f2(n:INT):INT ==
> l:List INT:=[]
> for x in -n..n repeat
> for y in -n..n | y >= x repeat
> l:=cons(x*x+x*y+y*y,l);
> #removeDuplicates!(l)
Building list should be OK, but our 'removeDuplicates!' has quadratic
behaviour. Try 'REMOVE_-DUPLICATES(l)$Lisp' instead.
> f3(n:INT):INT ==
> l:List INT:=[]
> for x in -n..n repeat
> for y in -n..n | y >= x repeat
> l:=concat!(l,x*x+x*y+y*y);
> #removeDuplicates!(l)
That is know anypattern which causes quadratic behaviour. Appending
at the end means that function has to travel trough the list first.
--
Waldek Hebisch