(defun key-quiz--shuffle-list (list) "Shuffles LIST randomly, modying it in-place." (dolist (i (reverse (number-sequence 1 (1- (length list))))) (let ((j (random (1+ i))) (tmp (elt list i))) (setf (elt list i) (elt list j)) (setf (elt list j) tmp))) list) (defun key-quiz--shuffle-list-nreverse (list) "Shuffles LIST randomly, modying it in-place." (dolist (i (nreverse (number-sequence 1 (1- (length list))))) (let ((j (random (1+ i))) (tmp (elt list i))) (setf (elt list i) (elt list j)) (setf (elt list j) tmp))) list) (defun elfeed--shuffle (seq) "Destructively shuffle SEQ." (let ((n (length seq))) (prog1 seq ; don't use dotimes result (bug#16206) (dotimes (i n) (cl-rotatef (elt seq i) (elt seq (+ i (random (- n i))))))))) (defun faster-seq-sort-by (function pred sequence) "Sort SEQUENCE using PRED as a comparison function. Elements of SEQUENCE are transformed by FUNCTION before being sorted. FUNCTION must be a function of one argument." ;; This version is modified to avoid calling "random" twice every time the predicate is called. (seq-map 'cdr (sort (seq-map (lambda (x) (cons (funcall function x) x)) sequence) (lambda (a b) (funcall pred (car a) (car b)))))) (defun seq-sort-by--shuffle (seq) (seq-sort-by (lambda (_) (random)) #'<= seq)) (defun faster-seq-sort-by--shuffle (seq) (faster-seq-sort-by (lambda (_) (random)) #'<= seq)) (dolist (sorter '(key-quiz--shuffle-list key-quiz--shuffle-list-nreverse elfeed--shuffle seq-sort-by--shuffle faster-seq-sort-by--shuffle )) (dolist (list-type '(list vector)) (let ((big-list (seq-into (seq-take obarray 5000) list-type)) (reps 100) ;;(gc-cons-threshold (* 128 1024 1024)) ) (message "*** %s - %s:" list-type sorter) (garbage-collect) (benchmark reps `(funcall ',sorter big-list)) )))