Mercurial > demo / examples/db/mini-redis.lisp
changeset 37: |
c6d0a37a046a |
child: |
8259376eee11 |
author: |
ellis <ellis@rwest.io> |
date: |
Sun, 24 Dec 2023 19:24:39 -0500 |
permissions: |
-rw-r--r-- |
description: |
mini-redis and vegadat |
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 6 (require 'sb-concurrency) 7 (defpackage :examples/mini-redis 8 (:use :cl :std :net :obj :cli :sb-concurrency :sb-thread) 11 (in-package :examples/mini-redis) 14 (make-castable :test #'equal)) 16 (defstruct conn tx rx) 18 (defun connect-to-server (server) 19 (let ((tx (make-mailbox)) 23 (let ((msg (receive-message tx))) 28 (multiple-value-bind (val p) 29 (obj/hash:cgethash (cdr msg) server) 31 (send-message rx `(:found ,val)) 32 (send-message rx `(:not-found))))) 34 (setf (cgethash (cadr msg) server) 35 (copy-seq (caddr msg))) 36 (send-message rx '(:ok))) 38 :name "mini-redis-conn") 39 (make-conn :tx tx :rx rx))) 41 (defun find-val (conn name) 45 (let ((rx (receive-message (conn-rx conn)))) 52 (defun (setf find-val) (val conn name) 59 (defun close-conn (conn) 64 (defun worker (n server 66 writer-proportion names) 67 (declare (optimize (speed 3)) 68 (single-float writer-proportion)) 69 (let ((name (elt names n)) 70 (bitmap (make-array 100 71 :element-type '(unsigned-byte 8) 73 (conn (connect-to-server server))) 76 (if (< (random 1.0) writer-proportion) 79 (signal-semaphore ready) 80 (wait-on-semaphore start) 82 (dotimes (o (the fixnum *ops*)) 83 (if (zerop (aref bitmap position)) 85 (setf (find-val conn name) 87 (setf position (mod (1+ position) 100)))) 90 (defparameter *worker-count* 8) 91 (defparameter *writer-proportion* 0.5) 93 (loop for n below 130 by 2 94 collect (format nil "~r" n))) 96 (loop for n from 1 below 128 by 2 97 collect (format nil "~r" n))) 98 (defvar *ops* 10000000) 100 (defun run (&optional (worker-count *worker-count*) 101 (writer-proportion *writer-proportion*) 103 (let* ((ready (make-semaphore :name "ready-threads")) 104 (start (make-semaphore :name "start-threads")) 105 (server (make-server)) 106 (workers (loop for n below worker-count 114 (dotimes (n worker-count) 115 (wait-on-semaphore ready)) 116 (let ((start-time (get-internal-real-time))) 117 (signal-semaphore start worker-count) 118 (mapc #'join-thread workers) 119 (let* ((time (float (/ (- (get-internal-real-time) start-time) 120 internal-time-units-per-second))) 121 (throughput (/ (* *ops* worker-count) time))) 122 (format t "~&~20@a: ~$ seconds (~d transactions/second)" 123 "mini-redis" time (round throughput))))))