minimart-benchmark-2017/internal-latency-prospect.rkt

117 lines
3.6 KiB
Racket

#lang racket/base
;; Measurement of message delivery latency.
(require racket/match)
(require prospect)
(require logbook)
(provide run)
(struct ping (src dst timestamp) #:transparent)
;; (define (current-microseconds)
;; (* (current-inexact-milliseconds) 1000.0))
(define (current-microseconds)
(modulo (* (current-inexact-milliseconds) 1000.0) 1000000000))
;; (define (current-microseconds)
;; (truncate (modulo (* (current-inexact-milliseconds) 1000.0) 1000000000)))
;; (define (current-microseconds)
;; (inexact->exact (truncate (modulo (* (current-inexact-milliseconds) 1000.0) 1000000000))))
(define (send-ping src dst)
(message (ping src dst (current-microseconds))))
(define (run #:echoer-count [echoer-count 100]
#:run-time [run-time 10000])
(define total-latency 0)
(define total-roundtrips 0)
(define boot-start-time (current-microseconds))
(define run-start-time #f)
(define (rate-at count)
(/ (* count 2) ;; two messages per roundtrip
(/ total-latency 1000000.0) ;; latency in seconds
))
(define (pinger src dst)
(spawn (lambda (e s)
(match e
[(message 'kickoff)
(set! run-start-time (current-microseconds))
(transition s (send-ping src dst))]
[(message (ping (== dst) (== src) start-time))
(define stop-time (current-microseconds))
;; TODO: is there a way of reducing the measurement error here,
;; perhaps by recording against run-start-time instead of start-time, somehow?
;; TODO: first, characterize the measurement error
(define delta (- stop-time start-time))
(set! total-latency (+ total-latency delta))
(set! total-roundtrips (+ total-roundtrips 1))
(when (zero? (modulo total-roundtrips 1000))
(log-info "After ~a roundtrips, ~a milliseconds; ~a Hz."
total-roundtrips
total-latency
(rate-at total-roundtrips)))
(transition s
(if (< (/ (- stop-time run-start-time) 1000.0) run-time)
(send-ping src dst)
'()))]
[_ #f]))
#f
(patch-seq (sub (ping dst src ?))
(sub 'kickoff)
(pub (ping src dst ?)))))
(define (echoer id)
(spawn (lambda (e s)
(match e
[(message (ping src (== id) stamp))
(transition s (message (ping id src stamp)))]
[_ #f]))
#f
(patch-seq (sub (ping ? id ?))
(pub (ping id ? ?)))))
(begin
(run-ground (for/list [(id (in-range echoer-count))] (echoer id))
(pinger echoer-count 0)
(message 'kickoff))
(values total-roundtrips (rate-at total-roundtrips) (- run-start-time boot-start-time))))
(module+ main
(define t 10000)
;; (define E (standard-logbook-entry (default-logbook #:verbose? #t) "minimart" "internal-latency-prospect"))
;; (define T (logbook-table E "internal-latency"
;; #:column-spec '(number-of-echoers
;; secs/msg
;; msgs/sec
;; boot-delay-ms
;; secs/process-booted
;; roundtrip-count
;; run-duration-ms)))
;; Warmup
(let ()
(run #:echoer-count 1 #:run-time 1000)
(run #:echoer-count 10 #:run-time 1000)
(void))
;; Real run
(for ((n
(list* 1 2 5
'()#;(let loop ((n 10))
(if (>= n 30000)
'()
(cons (inexact->exact (round n))
(loop (* n (sqrt (sqrt 2))))))))
))
(collect-garbage)
(collect-garbage)
(collect-garbage)
(define-values (count v boot-delay-ms) (run #:echoer-count n #:run-time t))
(void)#;(write-logbook-datum! T (list n
(/ 1.0 v)
v
boot-delay-ms
(/ (/ boot-delay-ms 1000.0) n)
count
t))))