io: add shortcut to get semaphore on blocking fd read
When reading from an input fd blocks, instead of creating a general event that creates a semaphore, use the semaphore directly (when available). Also, treat a semaphore internally as an event that always produces 0. This change speeds up the "echo" shootout benchmark. This change speeds up the "echo" shootout benchmark.
This commit is contained in:
parent
97e61b5f25
commit
1824fe5e41
|
@ -61,8 +61,8 @@
|
||||||
(end-atomic)
|
(end-atomic)
|
||||||
(send fd-input-port this raise-read-error n)]
|
(send fd-input-port this raise-read-error n)]
|
||||||
[(eqv? n RKTIO_READ_EOF) eof]
|
[(eqv? n RKTIO_READ_EOF) eof]
|
||||||
[(eqv? n 0) (wrap-evt (fd-evt fd RKTIO_POLL_READ this)
|
[(eqv? n 0) (or (fd-semaphore-update! fd 'read)
|
||||||
(lambda (v) 0))]
|
(fd-evt fd RKTIO_POLL_READ this))]
|
||||||
[else n]))]
|
[else n]))]
|
||||||
|
|
||||||
[close
|
[close
|
||||||
|
@ -379,6 +379,9 @@
|
||||||
|
|
||||||
;; ----------------------------------------
|
;; ----------------------------------------
|
||||||
|
|
||||||
|
;; The ready value for an `fd-evt` is 0, so it can be used directly
|
||||||
|
;; for an input port
|
||||||
|
|
||||||
(struct fd-evt (fd mode [closed #:mutable])
|
(struct fd-evt (fd mode [closed #:mutable])
|
||||||
#:property
|
#:property
|
||||||
prop:evt
|
prop:evt
|
||||||
|
@ -388,7 +391,7 @@
|
||||||
(lambda (fde ctx)
|
(lambda (fde ctx)
|
||||||
(cond
|
(cond
|
||||||
[(core-port-closed? (fd-evt-closed fde))
|
[(core-port-closed? (fd-evt-closed fde))
|
||||||
(values (list fde) #f)]
|
(values '(0) #f)]
|
||||||
[else
|
[else
|
||||||
(define mode (fd-evt-mode fde))
|
(define mode (fd-evt-mode fde))
|
||||||
(define ready?
|
(define ready?
|
||||||
|
@ -401,7 +404,7 @@
|
||||||
RKTIO_POLL_READY))))
|
RKTIO_POLL_READY))))
|
||||||
(cond
|
(cond
|
||||||
[ready?
|
[ready?
|
||||||
(values (list fde) #f)]
|
(values '(0) #f)]
|
||||||
;; If the called is going to block (i.e., not just polling), then
|
;; If the called is going to block (i.e., not just polling), then
|
||||||
;; try to get a semaphore to represent the file descriptor, because
|
;; try to get a semaphore to represent the file descriptor, because
|
||||||
;; that can be more scalable (especially for lots of TCP sockets)
|
;; that can be more scalable (especially for lots of TCP sockets)
|
||||||
|
@ -411,7 +414,7 @@
|
||||||
'read
|
'read
|
||||||
'write)))
|
'write)))
|
||||||
=> (lambda (s) ; got a semaphore
|
=> (lambda (s) ; got a semaphore
|
||||||
(values #f (wrap-evt s (lambda (s) fde))))]
|
(values #f (wrap-evt s (lambda (s) 0))))]
|
||||||
[else
|
[else
|
||||||
;; If `sched-info` in `poll-ctx` is not #f, then we can register this file
|
;; If `sched-info` in `poll-ctx` is not #f, then we can register this file
|
||||||
;; descriptor so that if no thread is able to make progress,
|
;; descriptor so that if no thread is able to make progress,
|
||||||
|
|
|
@ -74,7 +74,8 @@
|
||||||
;; be exposed to untrusted code, and instead of should be copied if
|
;; be exposed to untrusted code, and instead of should be copied if
|
||||||
;; necessary. The return values are the same as documented for
|
;; necessary. The return values are the same as documented for
|
||||||
;; `make-input-port`, except that a pipe result is not allowed (or,
|
;; `make-input-port`, except that a pipe result is not allowed (or,
|
||||||
;; more precisely, it's treated as an event).
|
;; more precisely, it's treated as an event), and a semaphore is
|
||||||
|
;; treated like an event that produces 0.
|
||||||
[read-in (lambda (bstr start end copy?) eof)]
|
[read-in (lambda (bstr start end copy?) eof)]
|
||||||
|
|
||||||
;; port or (bytes start-k end-k skip-k progress-evt copy? -*> (or/c integer? ...))
|
;; port or (bytes start-k end-k skip-k progress-evt copy? -*> (or/c integer? ...))
|
||||||
|
|
|
@ -101,6 +101,21 @@
|
||||||
"result" v
|
"result" v
|
||||||
"byte-string length" (- end start))])]
|
"byte-string length" (- end start))])]
|
||||||
[(eof-object? v) eof]
|
[(eof-object? v) eof]
|
||||||
|
[(semaphore? v)
|
||||||
|
;; A semaphore is treated as a special case, making
|
||||||
|
;; it equivalent to an evt that returns 0
|
||||||
|
(cond
|
||||||
|
[zero-ok?
|
||||||
|
;; Poll:
|
||||||
|
(cond
|
||||||
|
[(semaphore-try-wait? v)
|
||||||
|
(loop in extra-count-ins)]
|
||||||
|
[else 0])]
|
||||||
|
[else
|
||||||
|
(if enable-break?
|
||||||
|
(semaphore-wait/enable-break v)
|
||||||
|
(semaphore-wait v))
|
||||||
|
(loop in extra-count-ins)])]
|
||||||
[(evt? v)
|
[(evt? v)
|
||||||
;; If `zero-ok?`, we should at least poll the event
|
;; If `zero-ok?`, we should at least poll the event
|
||||||
(define timeout (if zero-ok? (lambda () 0) #f))
|
(define timeout (if zero-ok? (lambda () 0) #f))
|
||||||
|
@ -186,6 +201,14 @@
|
||||||
"result" v
|
"result" v
|
||||||
"byte-string length" (- end start))])]
|
"byte-string length" (- end start))])]
|
||||||
[(eof-object? v) eof]
|
[(eof-object? v) eof]
|
||||||
|
[(semaphore? v)
|
||||||
|
(cond
|
||||||
|
[zero-ok? 0]
|
||||||
|
[else
|
||||||
|
(if enable-break?
|
||||||
|
(semaphore-wait/enable-break v)
|
||||||
|
(semaphore-wait v))
|
||||||
|
(loop in)])]
|
||||||
[(evt? v)
|
[(evt? v)
|
||||||
(cond
|
(cond
|
||||||
[zero-ok? 0]
|
[zero-ok? 0]
|
||||||
|
|
Loading…
Reference in New Issue
Block a user