【发布时间】:2015-04-14 23:17:11
【问题描述】:
我正在尝试解决以下问题。我有一些实时运行的代理,具有几毫秒的大心跳,因此它们处理的操作顺序大多是确定性的(因为消息处理不是瓶颈)。
现在,我正在对不再有心跳的系统进行大量模拟(否则将需要几个世纪) - 但我需要确保保留操作顺序。为此,我采用了以下解决方案:模拟器确保每个代理都处理了他的消息队列,方法是发布一个虚拟同步消息并在等待答案时阻塞。这确实适用于我的应用程序,但它所花费的时间并不直观 - 因为单线程实现会快一个数量级(我猜 - x 100 ish - 虽然我没有测试过)。
我已经隔离了一个显示问题的小测试,甚至尝试使用另一个库 akka.net
type Greet =
| Greet of string
| Hello of AsyncReplyChannel<bool>
| Hello2
[<EntryPoint>]
let main argv =
let system = System.create "MySystem" <| Configuration.load()
let greeter = spawn system "greeter" <| fun mailbox ->
let rec loop() = actor {
let! msg = mailbox.Receive()
let sender = mailbox.Sender()
match msg with
| Greet who -> () // printf "Hello, %s!\n" who
| Hello2 -> sender.Tell(true)
| _ -> ()
return! loop()
}
loop()
let greeterF =
MailboxProcessor.Start
(fun inbox ->
async {
while true do
let! msg = inbox.Receive()
match msg with
| Greet who -> () // printf "Hello, %s!\n" who
| Hello reply -> reply.Reply true
| _ -> ()
}
)
let n = 1000000
let t1 = System.Diagnostics.Stopwatch()
t1.Start()
for i = 1 to n do
let rep = greeterF.PostAndReply(fun reply -> (Hello reply)) |> ignore
()
printfn "elapsed Mailbox:%A" t1.ElapsedMilliseconds
t1.Restart()
for i = 1 to n do
let res = greeter.Ask (Hello2)
let rr = res.Result
()
printfn "elapsed Akka:%A" t1.ElapsedMilliseconds
System.Console.ReadLine () |> ignore
0
基本上,仅仅 100 万次同步都需要大约 10 秒 - 而不是计算所涉及的任何内容,这……很不幸。
我想知道是否有人遇到过同样的问题,是否有任何方法可以关闭开销,强制所有内容以单线程模式运行……这比停用所有 cpu 更好,但在bios - 或者在没有代理的情况下编写整个系统的克隆。
非常感谢任何帮助。
【问题讨论】:
-
您确定这种开销在实际计算到位后会很明显吗?话虽如此,我对Hopac 的体验非常好,据称可以节省大量开销。
-
每个背后的实际计算大多是数字化的,归结为一堆基本操作——最多是这里和那里的几个内存分配。我认为没有太多的方法-锁定/线程切换等..慢了一个数量级。我想我必须投入一些硬件。听起来很傻,但很有效。
标签: performance optimization f# mailboxprocessor akka.net