1
0
mirror of synced 2026-02-27 01:19:42 +00:00
Files
Interlisp.medley/cl-bench/files/misc.lisp
Larry Masinter 02ed8d4bf4 add cl-benchmarks
benchmarks probably belong under internal/benchmarks
2020-09-16 23:17:10 -07:00

189 lines
5.5 KiB
Common Lisp

;;; misc.lisp
;;;
;;; Time-stamp: <2004-06-28 emarsden>
(in-package :cl-bench.misc)
(defun run-compiler ()
(compile-file (make-pathname :directory '(:relative "files")
:name "gabriel"
:type "olisp")
:print nil
#-gcl :verbose #-gcl nil))
(defun run-fasload ()
(load
(compile-file-pathname
(make-pathname :directory '(:relative "files")
:name "gabriel"
:type "olisp"))))
;; by Gene Luks (adapted from the Larceny benchmarks)
;
; Procedure P_n generates a grey code of all perms of n elements
; on top of stack ending with reversal of starting sequence
;
; F_n is flip of top n elements.
;
; procedure P_n
; if n>1 then
; begin
; repeat P_{n-1},F_n n-1 times;
; P_{n-1}
; end
(defun permutations (x)
(let* ((x x)
(perms (list x)))
(labels ((P (n)
(if (> n 1)
(do ((j (- n 1) (- j 1)))
((zerop j)
(P (- n 1)))
(P (- n 1))
(F n))))
(F (n)
(setf x (revloop x n (list-tail x n)))
(push x perms))
(revloop (x n y)
(if (zerop n) y
(revloop (cdr x)
(- n 1)
(cons (car x) y))))
(list-tail (x n)
(if (zerop n) x
(list-tail (cdr x) (- n 1)))))
(P (length x))
perms)))
(defun iota (n)
(do ((n n (- n 1))
(p '() (cons n p)))
((zerop n) p)))
(defun run-permutations ()
(let* ((perms (permutations (iota 9)))
(sums (mapcar (lambda (l) (reduce '+ l)) perms)))
(assert (eql 1 (length (remove-duplicates sums))))))
;; Destructive merge of two sorted lists.
;; From Hansen's MS thesis.
(defun merge! (a b predicate)
(labels ((merge-loop (r a b)
(cond ((funcall predicate (car b) (car a))
(setf (cdr r) b)
(if (null (cdr b))
(setf (cdr b) a)
(merge-loop b a (cdr b))))
(t ; (car a) <= (car b)
(setf (cdr r) a)
(if (null (cdr a))
(setf (cdr a) b)
(merge-loop a (cdr a) b))))))
(cond ((null a) b)
((null b) a)
((funcall predicate (car b) (car a))
(if (null (cdr b))
(setf (cdr b) a)
(merge-loop b a (cdr b)))
b)
(t ; (car a) <= (car b)
(if (null (cdr a))
(setf (cdr a) b)
(merge-loop a (cdr a) b))
a))))
;; Stable sort procedure which copies the input list and then sorts
;; the new list imperatively. On the systems we have benchmarked,
;; this generic list sort has been at least as fast and usually much
;; faster than the library's sort routine.
;; Due to Richard O'Keefe; algorithm attributed to D.H.D. Warren.
(defun sort! (seq predicate)
(labels ((astep (n)
(cond ((> n 2)
(let* ((j (truncate n 2))
(a (astep j))
(k (- n j))
(b (astep k)))
(merge! a b predicate)))
((= n 2)
(let ((x (car seq))
(y (cadr seq))
(p seq))
(setf seq (cddr seq))
(when (funcall predicate y x)
(setf (car p) y)
(setf (cadr p) x))
(setf (cddr p) nil)
p))
((= n 1)
(let ((p seq))
(setf seq (cdr seq))
(setf (cdr p) nil)
p))
(t nil))))
(astep (length seq))))
(defun integer-hash (key)
(declare (type (unsigned-byte 32) key))
(flet ((u32* (a b) (ldb (byte 32 0) (* a b)))
(u32-right-shift (integer count)
(ldb (byte 32 0) (ash integer count))))
(u32* (u32-right-shift key 3) 2654435761)))
(defun make-big-list (n)
(let ((list (list)))
(dotimes (i n)
(push (integer-hash n) list))
list))
(defparameter *big-seq-list* nil)
(defparameter *big-mess-list* nil)
;; This setup function is called before the main benchmark function,
;; without an intervening GC. The allocation time here doesn't count
;; towards the benchmark. It's important to avoid an intervening GC,
;; because the compaction resulting from the collector could skew
;; results (esp for /mess below).
(defun setup-walk-list/seq ()
(setf *big-seq-list* (make-big-list 2000000)))
;; walk the list to calculate its length
(defun walk-list/seq ()
(let (before after)
(setf before (length *big-seq-list*))
(push 42 *big-seq-list*)
(setf after (length *big-seq-list*))
(assert (eql after (1+ before)))
(setq *big-seq-list* nil)))
;; allocate a large list of fixnums, and merge-sort the list so that
;; pointers in the list are maximally spread out over memory.
(defun setup-walk-list/mess ()
(setf *big-mess-list* (make-big-list 2000000))
(sort! *big-mess-list* #'<))
(defun walk-list/mess ()
(let ((before 0)
(after 0))
(dolist (i *big-mess-list*)
(incf before))
(push 42 *big-mess-list*)
(dolist (i *big-mess-list*)
(incf after))
(assert (eql after (1+ before)))
(setq *big-mess-list* nil)))
;; EOF