git.iko.soy/distributed-process
on master help sign in
Use a non-blocking read first time we hit the mailbox, then drop back to blocking
commit6366fa4a8e132b07019a81a3a8ddd331d3817118 authorTim Watson <watson.timothy@gmail.com> dateThu 13 Mar 2014, 22:57 (13 years ago) parent218f762
1 file changed+3−50
src/Control/Distributed/Process/Management.hs+3−50
src/Control/Distributed/Process/Management.hs+3−50
@@ -534,40 +534,7 @@ mxAgentWithFinalize mxId initState handlers dtor = do
534534 , matchSTM (readTChan chan) return]
535535 InputChan -> [ matchSTM (readTChan chan) return
536536 , matchAny return]
537− in getNextInput' matches 100
538−
539− -- when reading inputs, we generally want to maintain a degree of
540− -- fairness in choosing between the TChan and our mailbox, but to
541− -- ultimately favour the TChan overall. We do this by flipping
542− -- between the two (using the ChannelSelector) each time we call
543− -- getNextInput - it returns the opposite ChannelSelector to the
544− -- one which succeeded last time it was called.
545−
546− -----------------------------------------------------------------------
547− --
548− -- This strategy works well, yet we wish to avoid blocking on one
549− -- input if the other is empty/busy, so we begin by reading both
550− -- sources conditionally - tryReadTChan for the event bus and
551− -- receiveTimeout for the mailbox. If polling (either source) does
552− -- not yield an input, we swap to the other, but we cannot continue
553− -- in this fashion ad infinitum, since that would waste considerable
554− -- system resoures. Instead, we switch ten times, after which (if no
555− -- data were obtained) we block on the event bus, since that is our
556− -- main priority.
557− -----------------------------------------------------------------------
558−
559− --
560− -- An agent can of course, choose to override which source should be
561− -- checked first. We consider this a /hint/ rather than a dictat.
562− -- When reading from the mailbox, we perform a non-blocking read.
563− -- We assume that most agents will prefer using mxReceiveChan to its
564− -- mailbox reading counterpart, this we expect the event bus to be
565− -- non-empty or the entire subsystem is likely doing very little work,
566− -- in which case we needn't worry too much about the overheads
567− -- described thus far.
568−
569− -- TODO: use mersenne-random / (System.Random.MWC) to get a
570− -- uniform distribution of values between 10..2000
537+ in getNextInput' matches 0
571538
572539 getNextInput' ms n = do
573540 mIn <- receiveTimeout n ms
@@ -576,22 +543,8 @@ mxAgentWithFinalize mxId initState handlers dtor = do
576543 Just msg -> return msg
577544
578545 tryNextInput ms n
579− | n < 2000 = getNextInput' ms $ n * 2
580− | otherwise = getNextInput' ms 100
581−
582− -- getNextInput' c' 0 = do
583− -- m <- liftIO $ atomically $ readTChan c'
584− -- return (m, Mailbox)
585− -- getNextInput' InputChan c' n = do
586− -- inputs <- liftIO $ atomically $ tryReadTChan c'
587− -- case inputs of
588− -- Nothing -> getNextInput' Mailbox c' (n - 1)
589− -- Just m -> return (m, Mailbox)
590− -- getNextInput' Mailbox c' n = do
591− -- m <- receiveTimeout 0 [ matchAny return ]
592− -- case m of
593− -- Nothing -> getNextInput' InputChan c' (n - 1)
594− -- Just msg -> return (msg, InputChan)
546+ | n > 0 && n < 2000 = getNextInput' ms $ n * 2
547+ | otherwise = getNextInput' ms 100
595548
596549 runAgentFinalizer :: MxAgent s () -> MxAgentState s -> Process ()
597550 runAgentFinalizer f s = ST.runStateT (unAgent f) s >>= return . fst