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 3 ;; concurrent hash-tables 5 ;; API compatible with: 6 ;; https://github.com/no-defun-allowed/concurrent-hash-tables 10 ;; https://dspace.mit.edu/bitstream/handle/1721.1/130693/1251799942-MIT.pdf 12 ;; https://github.com/TooBiased/growt - folklore = linear-probing, non growing hash-table 14 ;; https://github.com/Shinmera/luckless 16 ;; https://github.com/no-defun-allowed/luckless 18 ;; https://github.com/telekons/42nd-at-threadmill - based on NBHM (JVM) 20 ;; https://github.com/robert-strandh/SICL/tree/master/Code/Hash-tables/Linear-probing 22 ;; https://github.com/no-defun-allowed/simd-sicl-hash-table 24 ;; some CAS/Atomics resources for Linux: 26 ;; - https://www.kernel.org/doc/html/v4.12/core-api/atomic_ops.html 28 ;; - https://docs.kernel.org/core-api/wrappers/atomic_t.html 30 ;; - https://www.kernel.org/doc/Documentation/memory-barriers.txt 32 ;; - https://litux.nl/mirror/kerneldevelopment/0672327201/ch09lev1sec1.html 34 ;; - https://docs.kernel.org/core-api/refcount-vs-atomic.html 36 ;; - https://en.wikipedia.org/wiki/Compare-and-swap 38 ;; - https://lwn.net/Articles/847973/ 42 ;; several of the implementations above are ported in this library. 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. 49 ;; Test, test, test. We must compare every implementation and 50 ;; benchmark their performance with real workloads. 53 (in-package :obj/hash) 55 (deftype solist-element-designator () `(member ,@(list :addr :fixnum :string))) 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))))) 63 (defun show-bin (solist i) 64 (let ((node (aref (car (so-bins solist)) i)) 65 (bin-nbits (- +hash-nbits+ (cdr (so-bins solist)))) 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) #\.) 73 ((unbound-marker-p node) 77 (loop (let ((next (get-next node))) 78 (when (or (endp next) (evenp (node-hash 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))) 89 (bit-string (node-hash node)) (so-key node)) 91 (bit-string (node-hash node)) (so-key node))))) 95 (defun show-bins (solist) 96 (let ((bins (car (so-bins solist))) 97 (bin-nbits (- +hash-nbits+ (cdr (so-bins solist)))) 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))))) 114 (defun print-hashes (solist) 115 (do ((node (%node-next (so-head solist)) (%node-next node))) 117 (format t "~16x~@[ ~s~]~%" 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)