Tôi đang viết một chương trình có số lượng đại lý lớn lắng nghe các sự kiện và phản ứng trên chúng. Kể từ khi Control.Concurrent.Chan.dupChan
không được chấp nhận, tôi đã quyết định sử dụng TChan như được quảng cáo.Hiệu suất/khóa kém với STM
Hiệu suất của TChan tồi tệ hơn nhiều so với tôi mong đợi. Tôi có chương trình sau đây minh họa vấn đề này:
{-# LANGUAGE BangPatterns #-}
module Main where
import Control.Concurrent.STM
import Control.Concurrent
import System.Random(randomRIO)
import Control.Monad(forever, when)
allCoords :: [(Int,Int)]
allCoords = [(x,y) | x <- [0..99], y <- [0..99]]
randomCoords :: IO (Int,Int)
randomCoords = do
x <- randomRIO (0,99)
y <- randomRIO (0,99)
return (x,y)
main = do
chan <- newTChanIO :: IO (TChan ((Int,Int),Int))
let watcher p = do
chan' <- atomically $ dupTChan chan
forkIO $ forever $ do
[email protected](p',_counter) <- atomically $ readTChan chan'
when (p == p') (print r)
return()
mapM_ watcher allCoords
let go !cnt = do
xy <- randomCoords
atomically $ writeTChan chan (xy,cnt)
go (cnt+1)
go 1
Khi biên soạn (-O) và chạy một cái gì đó chương trình đầu tiên sẽ ra như thế này:
./tchantest ((0,25),341) ((0,33),523) ((0,33),654) ((0,35),196) ((0,48),181) ((0,48),446) ((1,15),676) ((1,50),260) ((1,78),561) ((2,30),622) ((2,38),383) ((2,41),365) ((2,50),596) ((2,57),194) ((3,19),259) ((3,27),344) ((3,33),65) ((3,37),124) ((3,49),109) ((3,72),91) ((3,87),637) ((3,96),14) ((4,0),34) ((4,17),390) ((4,73),381) ((4,74),217) ((4,78),150) ((5,7),476) ((5,27),207) ((5,47),197) ((5,49),543) ((5,53),641) ((5,58),175) ((5,70),497) ((5,88),421) ((5,89),617) ((6,0),15) ((6,4),322) ((6,16),661) ((6,18),405) ((6,30),526) ((6,50),183) ((6,61),528) ((7,0),74) ((7,28),479) ((7,66),418) ((7,72),318) ((7,79),101) ((7,84),462) ((7,98),669) ((8,5),126) ((8,64),113) ((8,77),154) ((8,83),265) ((9,4),253) ((9,26),220) ((9,41),255) ((9,63),51) ((9,64),229) ((9,73),621) ((9,76),384) ((9,92),569) ...
Và sau đó, tại một số điểm, sẽ ngừng viết bất cứ điều gì, trong khi vẫn tiêu thụ 100% cpu.
((20,56),186) ((20,58),558) ((20,68),277) ((20,76),102) ((21,5),396) ((21,7),84)
Khi quá trình này bị khóa nhanh hơn và xảy ra chỉ sau một vài dòng. Nó cũng sẽ tiêu thụ bất kỳ số lõi nào được tạo sẵn thông qua cờ RTS '-N.
Ngoài ra, hiệu suất có vẻ kém - chỉ khoảng 100 sự kiện mỗi giây được xử lý.
Đây có phải là lỗi trong STM hoặc tôi có hiểu nhầm điều gì đó về ngữ nghĩa của STM không?
Một điều bạn hiểu sai là 'Chan' sẽ đánh thức một độc giả trong khi' TChan' của STM sẽ đánh thức * tất cả * người đọc cho mỗi bài viết riêng lẻ. Bên cạnh đó, Neil Brown có một gợi ý tốt cho bạn trong câu trả lời của mình. –
Nó không phải là ngữ nghĩa của STM bạn hiểu lầm, đó là việc thực hiện. Nó được thực hiện với khóa lạc quan. Điều này làm cho nó phù hợp trong trường hợp bạn có nhiều ô có thể thay đổi độc lập và nhiều giao dịch muốn cập nhật các tập con thường không chồng chéo của chúng. Nó cũng làm cho nó rất không phù hợp trong trường hợp mọi giao dịch chạm vào cùng một ô có thể thay đổi - giống như TChan trong trường hợp này. – Carl
Ngay cả khi mọi giao dịch chạm vào cùng một ô có thể thay đổi bạn có thể thực hiện khá tốt miễn là đọc đủ chi phối viết. – sclv