changelog shortlog graph tags branches changeset files file revisions raw help

Mercurial > demo / annotate examples/db/mini-redis.lisp

changeset 38: 8259376eee11
parent: c6d0a37a046a
child: 1ef551e24009
author: ellis <ellis@rwest.io>
date: Fri, 29 Dec 2023 00:45:44 -0500
permissions: -rw-r--r--
description: examples
37
c6d0a37a046a mini-redis and vegadat
ellis <ellis@rwest.io>
parents:
diff changeset
1
 ;;; examples/db/mini-redis.lisp --- Mini-Redis client/server
c6d0a37a046a mini-redis and vegadat
ellis <ellis@rwest.io>
parents:
diff changeset
2
 
c6d0a37a046a mini-redis and vegadat
ellis <ellis@rwest.io>
parents:
diff changeset
3
 ;; based on https://github.com/no-defun-allowed/concurrent-hash-tables/blob/master/Examples/phony-redis.lisp
c6d0a37a046a mini-redis and vegadat
ellis <ellis@rwest.io>
parents:
diff changeset
4
 
38
8259376eee11 examples
ellis <ellis@rwest.io>
parents: 37
diff changeset
5
 ;; if the heap gets exhausted you probably want to trying increasing
8259376eee11 examples
ellis <ellis@rwest.io>
parents: 37
diff changeset
6
 ;; the dynamic-space-size at runtime.
8259376eee11 examples
ellis <ellis@rwest.io>
parents: 37
diff changeset
7
 
37
c6d0a37a046a mini-redis and vegadat
ellis <ellis@rwest.io>
parents:
diff changeset
8
 ;;; Code:
c6d0a37a046a mini-redis and vegadat
ellis <ellis@rwest.io>
parents:
diff changeset
9
 (defpackage :examples/mini-redis
c6d0a37a046a mini-redis and vegadat
ellis <ellis@rwest.io>
parents:
diff changeset
10
   (:use :cl :std :net :obj :cli :sb-concurrency :sb-thread)
38
8259376eee11 examples
ellis <ellis@rwest.io>
parents: 37
diff changeset
11
   (:export :main))
37
c6d0a37a046a mini-redis and vegadat
ellis <ellis@rwest.io>
parents:
diff changeset
12
 
c6d0a37a046a mini-redis and vegadat
ellis <ellis@rwest.io>
parents:
diff changeset
13
 (in-package :examples/mini-redis)
c6d0a37a046a mini-redis and vegadat
ellis <ellis@rwest.io>
parents:
diff changeset
14
 
38
8259376eee11 examples
ellis <ellis@rwest.io>
parents: 37
diff changeset
15
 (defparameter *worker-count* 4)
8259376eee11 examples
ellis <ellis@rwest.io>
parents: 37
diff changeset
16
 (defparameter *writer-proportion* 0.5)
8259376eee11 examples
ellis <ellis@rwest.io>
parents: 37
diff changeset
17
 (defvar *keys*
8259376eee11 examples
ellis <ellis@rwest.io>
parents: 37
diff changeset
18
   (loop for n below 130 by 2
8259376eee11 examples
ellis <ellis@rwest.io>
parents: 37
diff changeset
19
         collect (format nil "~r" n)))
8259376eee11 examples
ellis <ellis@rwest.io>
parents: 37
diff changeset
20
 (defvar *other-keys*
8259376eee11 examples
ellis <ellis@rwest.io>
parents: 37
diff changeset
21
   (loop for n from 1 below 128 by 2
8259376eee11 examples
ellis <ellis@rwest.io>
parents: 37
diff changeset
22
         collect (format nil "~r" n)))
8259376eee11 examples
ellis <ellis@rwest.io>
parents: 37
diff changeset
23
 (defvar *ops* 400000)
8259376eee11 examples
ellis <ellis@rwest.io>
parents: 37
diff changeset
24
 
37
c6d0a37a046a mini-redis and vegadat
ellis <ellis@rwest.io>
parents:
diff changeset
25
 (defun make-server ()
c6d0a37a046a mini-redis and vegadat
ellis <ellis@rwest.io>
parents:
diff changeset
26
   (make-castable :test #'equal))
c6d0a37a046a mini-redis and vegadat
ellis <ellis@rwest.io>
parents:
diff changeset
27
 
c6d0a37a046a mini-redis and vegadat
ellis <ellis@rwest.io>
parents:
diff changeset
28
 (defstruct conn tx rx)
c6d0a37a046a mini-redis and vegadat
ellis <ellis@rwest.io>
parents:
diff changeset
29
 
c6d0a37a046a mini-redis and vegadat
ellis <ellis@rwest.io>
parents:
diff changeset
30
 (defun connect-to-server (server)
c6d0a37a046a mini-redis and vegadat
ellis <ellis@rwest.io>
parents:
diff changeset
31
   (let ((tx (make-mailbox))
c6d0a37a046a mini-redis and vegadat
ellis <ellis@rwest.io>
parents:
diff changeset
32
         (rx (make-mailbox)))
c6d0a37a046a mini-redis and vegadat
ellis <ellis@rwest.io>
parents:
diff changeset
33
     (make-thread 
c6d0a37a046a mini-redis and vegadat
ellis <ellis@rwest.io>
parents:
diff changeset
34
      (lambda ()
c6d0a37a046a mini-redis and vegadat
ellis <ellis@rwest.io>
parents:
diff changeset
35
        (let ((msg (receive-message tx)))
c6d0a37a046a mini-redis and vegadat
ellis <ellis@rwest.io>
parents:
diff changeset
36
          (loop do
c6d0a37a046a mini-redis and vegadat
ellis <ellis@rwest.io>
parents:
diff changeset
37
            (case (car msg)
c6d0a37a046a mini-redis and vegadat
ellis <ellis@rwest.io>
parents:
diff changeset
38
              (:quit (return))
c6d0a37a046a mini-redis and vegadat
ellis <ellis@rwest.io>
parents:
diff changeset
39
              (:get 
c6d0a37a046a mini-redis and vegadat
ellis <ellis@rwest.io>
parents:
diff changeset
40
               (multiple-value-bind (val p)
38
8259376eee11 examples
ellis <ellis@rwest.io>
parents: 37
diff changeset
41
                   (getchash (cdr msg) server)
37
c6d0a37a046a mini-redis and vegadat
ellis <ellis@rwest.io>
parents:
diff changeset
42
                 (if p
c6d0a37a046a mini-redis and vegadat
ellis <ellis@rwest.io>
parents:
diff changeset
43
                     (send-message rx `(:found ,val))
c6d0a37a046a mini-redis and vegadat
ellis <ellis@rwest.io>
parents:
diff changeset
44
                     (send-message rx `(:not-found)))))
c6d0a37a046a mini-redis and vegadat
ellis <ellis@rwest.io>
parents:
diff changeset
45
              (:put
38
8259376eee11 examples
ellis <ellis@rwest.io>
parents: 37
diff changeset
46
               (setf (getchash (cadr msg) server)
37
c6d0a37a046a mini-redis and vegadat
ellis <ellis@rwest.io>
parents:
diff changeset
47
                     (copy-seq (caddr msg)))
c6d0a37a046a mini-redis and vegadat
ellis <ellis@rwest.io>
parents:
diff changeset
48
               (send-message rx '(:ok)))
c6d0a37a046a mini-redis and vegadat
ellis <ellis@rwest.io>
parents:
diff changeset
49
              (t (return))))))
c6d0a37a046a mini-redis and vegadat
ellis <ellis@rwest.io>
parents:
diff changeset
50
      :name "mini-redis-conn")
c6d0a37a046a mini-redis and vegadat
ellis <ellis@rwest.io>
parents:
diff changeset
51
     (make-conn :tx tx :rx rx)))
c6d0a37a046a mini-redis and vegadat
ellis <ellis@rwest.io>
parents:
diff changeset
52
 
c6d0a37a046a mini-redis and vegadat
ellis <ellis@rwest.io>
parents:
diff changeset
53
 (defun find-val (conn name)
c6d0a37a046a mini-redis and vegadat
ellis <ellis@rwest.io>
parents:
diff changeset
54
   (send-message
c6d0a37a046a mini-redis and vegadat
ellis <ellis@rwest.io>
parents:
diff changeset
55
    (conn-tx conn)
c6d0a37a046a mini-redis and vegadat
ellis <ellis@rwest.io>
parents:
diff changeset
56
    `(:get ,name))
c6d0a37a046a mini-redis and vegadat
ellis <ellis@rwest.io>
parents:
diff changeset
57
   (let ((rx (receive-message (conn-rx conn))))
c6d0a37a046a mini-redis and vegadat
ellis <ellis@rwest.io>
parents:
diff changeset
58
     (case (car rx)
c6d0a37a046a mini-redis and vegadat
ellis <ellis@rwest.io>
parents:
diff changeset
59
       (:found
c6d0a37a046a mini-redis and vegadat
ellis <ellis@rwest.io>
parents:
diff changeset
60
        (values (cdr rx) t))
c6d0a37a046a mini-redis and vegadat
ellis <ellis@rwest.io>
parents:
diff changeset
61
       (:not-found
c6d0a37a046a mini-redis and vegadat
ellis <ellis@rwest.io>
parents:
diff changeset
62
        (values nil nil)))))
c6d0a37a046a mini-redis and vegadat
ellis <ellis@rwest.io>
parents:
diff changeset
63
 
c6d0a37a046a mini-redis and vegadat
ellis <ellis@rwest.io>
parents:
diff changeset
64
 (defun (setf find-val) (val conn name)
c6d0a37a046a mini-redis and vegadat
ellis <ellis@rwest.io>
parents:
diff changeset
65
   (send-message
c6d0a37a046a mini-redis and vegadat
ellis <ellis@rwest.io>
parents:
diff changeset
66
    (conn-tx conn)
c6d0a37a046a mini-redis and vegadat
ellis <ellis@rwest.io>
parents:
diff changeset
67
    `(:put ,name ,val))
c6d0a37a046a mini-redis and vegadat
ellis <ellis@rwest.io>
parents:
diff changeset
68
   (receive-message
c6d0a37a046a mini-redis and vegadat
ellis <ellis@rwest.io>
parents:
diff changeset
69
    (conn-rx conn)))
c6d0a37a046a mini-redis and vegadat
ellis <ellis@rwest.io>
parents:
diff changeset
70
 
c6d0a37a046a mini-redis and vegadat
ellis <ellis@rwest.io>
parents:
diff changeset
71
 (defun close-conn (conn)
c6d0a37a046a mini-redis and vegadat
ellis <ellis@rwest.io>
parents:
diff changeset
72
   (send-message
c6d0a37a046a mini-redis and vegadat
ellis <ellis@rwest.io>
parents:
diff changeset
73
    (conn-tx conn)
c6d0a37a046a mini-redis and vegadat
ellis <ellis@rwest.io>
parents:
diff changeset
74
    `(:quit)))
c6d0a37a046a mini-redis and vegadat
ellis <ellis@rwest.io>
parents:
diff changeset
75
 
c6d0a37a046a mini-redis and vegadat
ellis <ellis@rwest.io>
parents:
diff changeset
76
 (defun worker (n server
c6d0a37a046a mini-redis and vegadat
ellis <ellis@rwest.io>
parents:
diff changeset
77
                ready start
c6d0a37a046a mini-redis and vegadat
ellis <ellis@rwest.io>
parents:
diff changeset
78
                writer-proportion names)
c6d0a37a046a mini-redis and vegadat
ellis <ellis@rwest.io>
parents:
diff changeset
79
   (declare (optimize (speed 3))
c6d0a37a046a mini-redis and vegadat
ellis <ellis@rwest.io>
parents:
diff changeset
80
            (single-float writer-proportion))
c6d0a37a046a mini-redis and vegadat
ellis <ellis@rwest.io>
parents:
diff changeset
81
   (let ((name (elt names n))
c6d0a37a046a mini-redis and vegadat
ellis <ellis@rwest.io>
parents:
diff changeset
82
         (bitmap (make-array 100
c6d0a37a046a mini-redis and vegadat
ellis <ellis@rwest.io>
parents:
diff changeset
83
                             :element-type '(unsigned-byte 8)
c6d0a37a046a mini-redis and vegadat
ellis <ellis@rwest.io>
parents:
diff changeset
84
                             :initial-element 0))
c6d0a37a046a mini-redis and vegadat
ellis <ellis@rwest.io>
parents:
diff changeset
85
         (conn (connect-to-server server)))
c6d0a37a046a mini-redis and vegadat
ellis <ellis@rwest.io>
parents:
diff changeset
86
     (dotimes (i 100)
c6d0a37a046a mini-redis and vegadat
ellis <ellis@rwest.io>
parents:
diff changeset
87
       (setf (aref bitmap i)
c6d0a37a046a mini-redis and vegadat
ellis <ellis@rwest.io>
parents:
diff changeset
88
             (if (< (random 1.0) writer-proportion)
c6d0a37a046a mini-redis and vegadat
ellis <ellis@rwest.io>
parents:
diff changeset
89
                 1
c6d0a37a046a mini-redis and vegadat
ellis <ellis@rwest.io>
parents:
diff changeset
90
                 0)))
c6d0a37a046a mini-redis and vegadat
ellis <ellis@rwest.io>
parents:
diff changeset
91
     (signal-semaphore ready)
c6d0a37a046a mini-redis and vegadat
ellis <ellis@rwest.io>
parents:
diff changeset
92
     (wait-on-semaphore start)
c6d0a37a046a mini-redis and vegadat
ellis <ellis@rwest.io>
parents:
diff changeset
93
     (let ((position 0))
c6d0a37a046a mini-redis and vegadat
ellis <ellis@rwest.io>
parents:
diff changeset
94
       (dotimes (o (the fixnum *ops*))
c6d0a37a046a mini-redis and vegadat
ellis <ellis@rwest.io>
parents:
diff changeset
95
         (if (zerop (aref bitmap position))
c6d0a37a046a mini-redis and vegadat
ellis <ellis@rwest.io>
parents:
diff changeset
96
             (find-val conn name)
c6d0a37a046a mini-redis and vegadat
ellis <ellis@rwest.io>
parents:
diff changeset
97
             (setf (find-val conn name)
c6d0a37a046a mini-redis and vegadat
ellis <ellis@rwest.io>
parents:
diff changeset
98
                   #(1)))
c6d0a37a046a mini-redis and vegadat
ellis <ellis@rwest.io>
parents:
diff changeset
99
         (setf position (mod (1+ position) 100))))
c6d0a37a046a mini-redis and vegadat
ellis <ellis@rwest.io>
parents:
diff changeset
100
     (close-conn conn)))
c6d0a37a046a mini-redis and vegadat
ellis <ellis@rwest.io>
parents:
diff changeset
101
 
c6d0a37a046a mini-redis and vegadat
ellis <ellis@rwest.io>
parents:
diff changeset
102
 (defun run (&optional (worker-count *worker-count*)
c6d0a37a046a mini-redis and vegadat
ellis <ellis@rwest.io>
parents:
diff changeset
103
               (writer-proportion *writer-proportion*)
c6d0a37a046a mini-redis and vegadat
ellis <ellis@rwest.io>
parents:
diff changeset
104
               (keys *keys*))
c6d0a37a046a mini-redis and vegadat
ellis <ellis@rwest.io>
parents:
diff changeset
105
   (let* ((ready (make-semaphore :name "ready-threads"))
c6d0a37a046a mini-redis and vegadat
ellis <ellis@rwest.io>
parents:
diff changeset
106
          (start (make-semaphore :name "start-threads"))
c6d0a37a046a mini-redis and vegadat
ellis <ellis@rwest.io>
parents:
diff changeset
107
          (server (make-server))
c6d0a37a046a mini-redis and vegadat
ellis <ellis@rwest.io>
parents:
diff changeset
108
          (workers (loop for n below worker-count
c6d0a37a046a mini-redis and vegadat
ellis <ellis@rwest.io>
parents:
diff changeset
109
                         collect (let ((n n))
c6d0a37a046a mini-redis and vegadat
ellis <ellis@rwest.io>
parents:
diff changeset
110
                                   (make-thread
c6d0a37a046a mini-redis and vegadat
ellis <ellis@rwest.io>
parents:
diff changeset
111
                                    (lambda ()
c6d0a37a046a mini-redis and vegadat
ellis <ellis@rwest.io>
parents:
diff changeset
112
                                      (worker n server
c6d0a37a046a mini-redis and vegadat
ellis <ellis@rwest.io>
parents:
diff changeset
113
                                              ready start
c6d0a37a046a mini-redis and vegadat
ellis <ellis@rwest.io>
parents:
diff changeset
114
                                              writer-proportion
c6d0a37a046a mini-redis and vegadat
ellis <ellis@rwest.io>
parents:
diff changeset
115
                                              keys)))))))
c6d0a37a046a mini-redis and vegadat
ellis <ellis@rwest.io>
parents:
diff changeset
116
     (dotimes (n worker-count)
c6d0a37a046a mini-redis and vegadat
ellis <ellis@rwest.io>
parents:
diff changeset
117
       (wait-on-semaphore ready))
c6d0a37a046a mini-redis and vegadat
ellis <ellis@rwest.io>
parents:
diff changeset
118
     (let ((start-time (get-internal-real-time)))
c6d0a37a046a mini-redis and vegadat
ellis <ellis@rwest.io>
parents:
diff changeset
119
       (signal-semaphore start worker-count)
c6d0a37a046a mini-redis and vegadat
ellis <ellis@rwest.io>
parents:
diff changeset
120
       (mapc #'join-thread workers)
c6d0a37a046a mini-redis and vegadat
ellis <ellis@rwest.io>
parents:
diff changeset
121
       (let* ((time (float (/ (- (get-internal-real-time) start-time)
c6d0a37a046a mini-redis and vegadat
ellis <ellis@rwest.io>
parents:
diff changeset
122
                              internal-time-units-per-second)))
c6d0a37a046a mini-redis and vegadat
ellis <ellis@rwest.io>
parents:
diff changeset
123
              (throughput (/ (* *ops* worker-count) time)))
c6d0a37a046a mini-redis and vegadat
ellis <ellis@rwest.io>
parents:
diff changeset
124
         (format t "~&~20@a: ~$ seconds (~d transactions/second)"
38
8259376eee11 examples
ellis <ellis@rwest.io>
parents: 37
diff changeset
125
                 "mini-redis" time (round throughput))))
8259376eee11 examples
ellis <ellis@rwest.io>
parents: 37
diff changeset
126
     server))
37
c6d0a37a046a mini-redis and vegadat
ellis <ellis@rwest.io>
parents:
diff changeset
127
 
c6d0a37a046a mini-redis and vegadat
ellis <ellis@rwest.io>
parents:
diff changeset
128
 (defmain ()
38
8259376eee11 examples
ellis <ellis@rwest.io>
parents: 37
diff changeset
129
   (run))