[Ecls-list] About new_cons branch
Juan Jose Garcia-Ripoll
jjgarcia at users.sourceforge.net
Tue Mar 4 09:32:33 UTC 2008
Hi,
it seems I am getting some real improvements there. As I mentioned,
creating the LIST type and moving NIL there, reduces quite
significantly the amount of checks to be done when looping over lists,
concatenating them, etc. By coding the list routines I am getting
speedups of up to 50% in some routines. Just to show this, the
following is a benchmark of current ECL (main branch, no improvements)
Name Real(s) Run(s) GC(kb) Repetitions
NCONC-2 0.488 .4783 15626 1000000
NCONC-3 .4998 .4925 31251 1000000
LIST* 0.897 .8823 156251 1000000
LIST .8975 .8703 156251 1000000
APPEND .8293 .8145 156251 100000
MAKE-LIST .7632 .7528 156251 100000
COPY-LIST 0.823 .8045 156251 100000
COPY-ALIST .8338 .8212 156251 100000
LAST-0 .4167 0.413 1 1000000
LAST-1 .4138 .4097 1 1000000
LAST-2 .4147 .4097 1 1000000
And this is what the new_cons branch produces
Name Real(s) Run(s) GC(kb) Repetitions
NCONC-2 .3175 .3117 15626 1000000
NCONC-3 .4317 .4247 31251 1000000
LIST* .5905 .5797 156251 1000000
LIST 0.577 0.567 156251 1000000
APPEND .4885 .4758 157814 100000
MAKE-LIST .4892 .4778 156251 100000
COPY-LIST .4845 .4648 156251 100000
COPY-ALIST .5415 .5292 156251 100000
LAST-0 .2753 .2702 1 1000000
LAST-1 .2485 0.243 1 1000000
LAST-2 .2745 .2712 1 1000000
We are not yet there. I expect further improvements by turning NIL
into a fixed word, namely 0x00003, instead of reference to a global
variable. The reason is that, at least on Mac OS X, when NIL is a
global variable, a function has to be called to find its address.
However, this is an even more delicate change and will be postponed
until more functions operating with lists have been optimized / fixed.
Juanjo
P.S.: This is the code I use to benchmark the implementation.
MAKE-LIST serves as a reference, because, since it only involves
consing simple objects, a function creating lists cannot really get
much faster than that.
(defvar *forms*
'((nconc-2 (setf x (cdr (nconc x (list 1)))) 1000000)
(nconc-3 (setf x (cddr (nconc x (list 1) (list 2)))) 1000000)
(list* (list* 0 1 2 3 4 5 6 7 8 9 10) 1000000)
(list (list 0 1 2 3 4 5 6 7 8 9) 1000000)
(append (locally (declare (notinline append))
(append x '(1))) 100000)
(make-list (make-list 100) 100000)
(copy-list (copy-list x) 100000)
(copy-alist (copy-alist x) 100000)
(last-0 (last x 0) 1000000)
(last-1 (last x) 1000000)
(last-2 (last x 2) 1000000)
))
(defun test1 (compiled-form)
(si:gc t)
(let* ((gc-start (si::gc-stats t))
(real-start (get-internal-real-time))
(run-start (get-internal-run-time)))
(funcall compiled-form)
(let* ((real-end (get-internal-real-time))
(run-end (get-internal-run-time))
(gc-end (progn (si:gc t) (si::gc-stats nil))))
(values
(/ (- real-end real-start) internal-time-units-per-second)
(/ (- run-end run-start) internal-time-units-per-second)
(- gc-end gc-start)))))
(defun compile-test (record)
(let* ((form (second record))
(times (third record))
(s-form `(lambda ()
(let ((x (make-list 100)))
(dotimes (i ,times)
,form))))
(form (let ((*compile-verbose* nil)) (compile 'nil s-form))))
(list (first record) form (third record))))
(defun test (name form times)
(let* ((real 0)
(run 0)
(gc 0)
(repetitions 6))
(dotimes (i repetitions)
(multiple-value-bind (r rn g)
(test1 form)
(incf real r)
(incf run rn)
(incf gc g)))
(format t "~10A ~5F ~5F~10D~15D~%"
name (float (/ real repetitions)) (float (/ run repetitions))
(floor gc (* repetitions 1024))
times)
(force-output *standard-output*)))
(require 'cmp)
(terpri)
(format t "~10A~@10A~@10A~@10A~@15A~%"
"Name" "Real(s)" "Run(s)" "GC(kb)" "Repetitions")
(dolist (i (mapcar #'compile-test *forms*))
(apply #'test i))
(quit)
--
Facultad de Fisicas, Universidad Complutense,
Ciudad Universitaria s/n Madrid 28040 (Spain)
http://juanjose.garciaripoll.googlepages.com
More information about the ecl-devel
mailing list