Skip to content

Commit 1573142

Browse files
committed
Task: Add benchmarking sequence shuffling
1 parent 748320b commit 1573142

File tree

2 files changed

+199
-5
lines changed

2 files changed

+199
-5
lines changed

README.org

Lines changed: 94 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -2652,6 +2652,100 @@ Describe things like exporting an Org readme to an Info manual, e.g. like Magit,
26522652

26532653
[2017-07-29 Sat 00:33] Not only should you test installing and using your package in the sandbox, but you should /also/ test then exiting the sandbox Emacs, running it again with the package already installed, and loading it. This is because, when the sandbox installs the package, the byte-compilation seems to load some things that won't be loaded the same way when only loading the byte-compiled file (especially if you have any ~eval-when-compile~ lines, or unusual macros or things that modify the environment when loaded).
26542654

2655+
** TODO Sequence shuffling examples and benchmarks
2656+
*** Benchmarking sequence shuffling
2657+
2658+
See https://github.com/melpa/melpa/pull/6191#issuecomment-498101336
2659+
2660+
#+BEGIN_SRC elisp
2661+
(defun key-quiz--shuffle-list (list)
2662+
"Shuffles LIST randomly, modying it in-place."
2663+
(dolist (i (reverse (number-sequence 1 (1- (length list)))))
2664+
(let ((j (random (1+ i)))
2665+
(tmp (elt list i)))
2666+
(setf (elt list i) (elt list j))
2667+
(setf (elt list j) tmp)))
2668+
list)
2669+
2670+
(defun key-quiz--shuffle-list-nreverse (list)
2671+
"Shuffles LIST randomly, modying it in-place."
2672+
(dolist (i (nreverse (number-sequence 1 (1- (length list)))))
2673+
(let ((j (random (1+ i)))
2674+
(tmp (elt list i)))
2675+
(setf (elt list i) (elt list j))
2676+
(setf (elt list j) tmp)))
2677+
list)
2678+
2679+
(defun elfeed--shuffle (seq)
2680+
"Destructively shuffle SEQ."
2681+
(let ((n (length seq)))
2682+
(prog1 seq ; don't use dotimes result (bug#16206)
2683+
(dotimes (i n)
2684+
(cl-rotatef (elt seq i) (elt seq (+ i (random (- n i)))))))))
2685+
2686+
(defun faster-seq-sort-by (function pred sequence)
2687+
"Sort SEQUENCE using PRED as a comparison function.
2688+
Elements of SEQUENCE are transformed by FUNCTION before being
2689+
sorted. FUNCTION must be a function of one argument."
2690+
;; This version is modified to avoid calling "random" twice every time the predicate is called.
2691+
(seq-map 'cdr
2692+
(sort (seq-map (lambda (x) (cons (funcall function x) x)) sequence)
2693+
(lambda (a b)
2694+
(funcall pred (car a) (car b))))))
2695+
2696+
(defun seq-sort-by--shuffle (seq)
2697+
(seq-sort-by (lambda (_) (random)) #'<= seq))
2698+
2699+
(defun faster-seq-sort-by--shuffle (seq)
2700+
(faster-seq-sort-by (lambda (_) (random)) #'<= seq))
2701+
#+END_SRC
2702+
2703+
#+RESULTS:
2704+
: faster-seq-sort-by--shuffle
2705+
2706+
**** Lists
2707+
2708+
#+BEGIN_SRC elisp
2709+
(let ((big-list (seq-into (seq-take obarray 5000) 'list)))
2710+
(bench-multi-lexical :times 100
2711+
:forms (("key-quiz--shuffle-list" (key-quiz--shuffle-list big-list))
2712+
("key-quiz--shuffle-list-nreverse" (key-quiz--shuffle-list-nreverse big-list))
2713+
("elfeed--shuffle" (elfeed--shuffle big-list))
2714+
("seq-sort-by--shuffle" (seq-sort-by--shuffle big-list))
2715+
("faster-seq-sort-by--shuffle" (faster-seq-sort-by--shuffle big-list)))))
2716+
#+END_SRC
2717+
2718+
#+RESULTS:
2719+
| Form | x faster than next | Total runtime | # of GCs | Total GC runtime |
2720+
|---------------------------------+--------------------+---------------+----------+------------------|
2721+
| faster-seq-sort-by--shuffle | 1.38 | 1.725037 | 0 | 0 |
2722+
| seq-sort-by--shuffle | 15.01 | 2.378234 | 0 | 0 |
2723+
| key-quiz--shuffle-list-nreverse | 1.03 | 35.703316 | 27 | 17.892723 |
2724+
| key-quiz--shuffle-list | 1.24 | 36.630320 | 28 | 18.768216 |
2725+
| elfeed--shuffle | slowest | 45.439405 | 32 | 21.130538 |
2726+
2727+
2728+
**** Vectors
2729+
2730+
#+BEGIN_SRC elisp
2731+
(let ((big-list (seq-into (seq-take obarray 5000) 'vector)))
2732+
(bench-multi-lexical :times 100
2733+
:forms (("key-quiz--shuffle-list" (key-quiz--shuffle-list big-list))
2734+
("key-quiz--shuffle-list-nreverse" (key-quiz--shuffle-list-nreverse big-list))
2735+
("elfeed--shuffle" (elfeed--shuffle big-list))
2736+
("seq-sort-by--shuffle" (seq-sort-by--shuffle big-list))
2737+
("faster-seq-sort-by--shuffle" (faster-seq-sort-by--shuffle big-list)))))
2738+
#+END_SRC
2739+
2740+
#+RESULTS:
2741+
| Form | x faster than next | Total runtime | # of GCs | Total GC runtime |
2742+
|---------------------------------+--------------------+---------------+----------+------------------|
2743+
| faster-seq-sort-by--shuffle | 1.39 | 1.718990 | 0 | 0 |
2744+
| seq-sort-by--shuffle | 10.42 | 2.390860 | 0 | 0 |
2745+
| key-quiz--shuffle-list-nreverse | 1.02 | 24.918774 | 27 | 17.971779 |
2746+
| key-quiz--shuffle-list | 1.10 | 25.452665 | 28 | 18.487015 |
2747+
| elfeed--shuffle | slowest | 27.991305 | 32 | 21.215224 |
2748+
26552749
* Code
26562750
:PROPERTIES:
26572751
:TOC: 0

0 commit comments

Comments
 (0)