changelog shortlog graph tags branches changeset files revisions annotate raw help

Mercurial > core / lisp/lib/obj/hash/chash.lisp

changeset 698: 96958d3eb5b0
parent: 9e7d4393eac6
author: Richard Westhaver <ellis@rwest.io>
date: Fri, 04 Oct 2024 22:04:59 -0400
permissions: -rw-r--r--
description: fixes
1 ;;; lib/obj/hash/chash.lisp --- Concurrent Hash Tables
2 
3 ;; concurrent hash-tables
4 
5 ;; API compatible with:
6 ;; https://github.com/no-defun-allowed/concurrent-hash-tables
7 
8 ;;; Resources:
9 
10 ;; https://dspace.mit.edu/bitstream/handle/1721.1/130693/1251799942-MIT.pdf
11 
12 ;; https://github.com/TooBiased/growt - folklore = linear-probing, non growing hash-table
13 
14 ;; https://github.com/Shinmera/luckless
15 
16 ;; https://github.com/no-defun-allowed/luckless
17 
18 ;; https://github.com/telekons/42nd-at-threadmill - based on NBHM (JVM)
19 
20 ;; https://github.com/robert-strandh/SICL/tree/master/Code/Hash-tables/Linear-probing
21 
22 ;; https://github.com/no-defun-allowed/simd-sicl-hash-table
23 
24 ;; some CAS/Atomics resources for Linux:
25 
26 ;; - https://www.kernel.org/doc/html/v4.12/core-api/atomic_ops.html
27 
28 ;; - https://docs.kernel.org/core-api/wrappers/atomic_t.html
29 
30 ;; - https://www.kernel.org/doc/Documentation/memory-barriers.txt
31 
32 ;; - https://litux.nl/mirror/kerneldevelopment/0672327201/ch09lev1sec1.html
33 
34 ;; - https://docs.kernel.org/core-api/refcount-vs-atomic.html
35 
36 ;; - https://en.wikipedia.org/wiki/Compare-and-swap
37 
38 ;; - https://lwn.net/Articles/847973/
39 
40 ;;; Notes:
41 
42 ;; several of the implementations above are ported in this library.
43 
44 ;; In general we rely on CAS operations to implement as
45 ;; lock-free. Typically you will still need some form of thread
46 ;; protection at higher levels of abstraction when working with these
47 ;; type of data structures.
48 
49 ;; Test, test, test. We must compare every implementation and
50 ;; benchmark their performance with real workloads.
51 
52 ;;; Code:
53 (in-package :obj/hash)
54 
55 (deftype solist-element-designator () `(member ,@(list :addr :fixnum :string)))
56 
57 (defun show-list (solist)
58  (let ((node (so-head solist)))
59  (loop (format t "~s~%" node)
60  (when (endp node) (return))
61  (setq node (%node-next node)))))
62 
63 (defun show-bin (solist i)
64  (let ((node (aref (car (so-bins solist)) i))
65  (bin-nbits (- +hash-nbits+ (cdr (so-bins solist))))
66  (count 0))
67  (flet ((bit-string (hash)
68  (let ((s (format nil " ~v,'0b" +hash-nbits+ hash)))
69  (replace s s :end1 bin-nbits :start2 1)
70  (setf (char s bin-nbits) #\.)
71  s)))
72  (cond
73  ((unbound-marker-p node)
74  (values 0 0))
75  (t
76  (let ((node node))
77  (loop (let ((next (get-next node)))
78  (when (or (endp next) (evenp (node-hash next)))
79  (return))
80  (incf count)
81  (setq node next))))
82  (format t " ~5d [~2d] = ~a" i count (bit-string (node-hash node)))
83  (loop (let ((next (get-next node)))
84  (when (or (endp next) (evenp (node-hash next)))
85  (return))
86  (setq node next)
87  (if (= count 1)
88  (format t " ~a=~s"
89  (bit-string (node-hash node)) (so-key node))
90  (format t "~% ~a=~s"
91  (bit-string (node-hash node)) (so-key node)))))
92  (terpri)
93  (values 1 count))))))
94 
95 (defun show-bins (solist)
96  (let ((bins (car (so-bins solist)))
97  (bin-nbits (- +hash-nbits+ (cdr (so-bins solist))))
98  (n-occupied-bins 0)
99  (sum-chainlengths 0)
100  (max-chainlength 0))
101  (assert (= (length bins) (ash 1 bin-nbits)))
102  (format t "Bins (~d total, ~d leading bits):~%"
103  (length bins) bin-nbits)
104  (dotimes (i (length bins))
105  (multiple-value-bind (occupied count) (show-bin solist i)
106  (incf n-occupied-bins occupied)
107  (incf sum-chainlengths count)
108  (setq max-chainlength (max count max-chainlength))))
109  (let ((avg-chainlength (/ sum-chainlengths n-occupied-bins)))
110  (format t "~&Total ~D items, avg ~F items/bin~%"
111  (so-count solist) avg-chainlength)
112  (values max-chainlength (float avg-chainlength)))))
113 
114 (defun print-hashes (solist)
115  (do ((node (%node-next (so-head solist)) (%node-next node)))
116  ((endp node))
117  (format t "~16x~@[ ~s~]~%"
118  (node-hash node)
119  (if (so-key-node-p node) (type-of (so-key node))))))
120 (sb-lockless:lfl-insert (sb-lockless:make-ordered-list :key-type 'fixnum) 5 'five)