Mercurial > demo / 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 |
1 ;;; examples/db/mini-redis.lisp --- Mini-Redis client/server 3 ;; based on https://github.com/no-defun-allowed/concurrent-hash-tables/blob/master/Examples/phony-redis.lisp 5 ;; if the heap gets exhausted you probably want to trying increasing 6 ;; the dynamic-space-size at runtime. 9 (defpackage :examples/mini-redis 10 (:use :cl :std :net :obj :cli :sb-concurrency :sb-thread) 13 (in-package :examples/mini-redis) 15 (defparameter *worker-count* 4) 16 (defparameter *writer-proportion* 0.5) 18 (loop for n below 130 by 2 19 collect (format nil "~r" n))) 21 (loop for n from 1 below 128 by 2 22 collect (format nil "~r" n))) 26 (make-castable :test #'equal)) 28 (defstruct conn tx rx) 30 (defun connect-to-server (server) 31 (let ((tx (make-mailbox)) 35 (let ((msg (receive-message tx))) 40 (multiple-value-bind (val p) 41 (getchash (cdr msg) server) 43 (send-message rx `(:found ,val)) 44 (send-message rx `(:not-found))))) 46 (setf (getchash (cadr msg) server) 47 (copy-seq (caddr msg))) 48 (send-message rx '(:ok))) 50 :name "mini-redis-conn") 51 (make-conn :tx tx :rx rx))) 53 (defun find-val (conn name) 57 (let ((rx (receive-message (conn-rx conn)))) 64 (defun (setf find-val) (val conn name) 71 (defun close-conn (conn) 76 (defun worker (n server 78 writer-proportion names) 79 (declare (optimize (speed 3)) 80 (single-float writer-proportion)) 81 (let ((name (elt names n)) 82 (bitmap (make-array 100 83 :element-type '(unsigned-byte 8) 85 (conn (connect-to-server server))) 88 (if (< (random 1.0) writer-proportion) 91 (signal-semaphore ready) 92 (wait-on-semaphore start) 94 (dotimes (o (the fixnum *ops*)) 95 (if (zerop (aref bitmap position)) 97 (setf (find-val conn name) 99 (setf position (mod (1+ position) 100)))) 102 (defun run (&optional (worker-count *worker-count*) 103 (writer-proportion *writer-proportion*) 105 (let* ((ready (make-semaphore :name "ready-threads")) 106 (start (make-semaphore :name "start-threads")) 107 (server (make-server)) 108 (workers (loop for n below worker-count 116 (dotimes (n worker-count) 117 (wait-on-semaphore ready)) 118 (let ((start-time (get-internal-real-time))) 119 (signal-semaphore start worker-count) 120 (mapc #'join-thread workers) 121 (let* ((time (float (/ (- (get-internal-real-time) start-time) 122 internal-time-units-per-second))) 123 (throughput (/ (* *ops* worker-count) time))) 124 (format t "~&~20@a: ~$ seconds (~d transactions/second)" 125 "mini-redis" time (round throughput))))