Erlang:优先接收
Erlang 中的优先接收可以很容易地实现如下:
prio() ->
receive
{priority, X} -> X
after 0 ->
receive
X -> X
end
end.
我正在阅读一篇名为 优先消息传递变得简单,作者:Nyström,他们在其中描述了以下问题:
[上面]的[代码]示例的主要问题是,我们没有考虑到当从内部阻塞接收恢复评估时,我们的邮箱中可能有多于一条消息。 在最坏的情况下,除了可能数量巨大的第一个元素之外的所有元素都可能是优先级消息。 在这种情况下,我们实际上会完成与我们想要做的事情恰恰相反的事情。
我不完全明白这一点。
问题(1):我假设一旦一条消息到达消息队列,内部阻塞接收就会被“调用”(即恢复),对吧? 假设在从内部阻塞接收恢复所需的短时间内,队列中已经有一大堆消息在等待,这是否现实?
问题(2):另外,最坏的情况被描述为队列中有一条普通消息和大量优先级消息。 由于所有接收子句首先针对队列中的第一条消息进行检查,然后针对队列中的第二条消息进行检查,...(来源:此 book,第 69-70 页)这不应该是:许多普通消息在队列末尾带有优先级消息吗?
Priority receive in Erlang can easily be implemented as follows:
prio() ->
receive
{priority, X} -> X
after 0 ->
receive
X -> X
end
end.
I am reading a paper called Priority Messaging made Easy, by Nyström, in which they describe the following problem:
The main problem with the [code] example [above], is that we do not take into consideration that when evaluation is resumed from the inner blocking receive we may have more than one message in the mailbox. In a worst case scenario, all but the first, of potentially a huge number, of elements could be priority messages. In this scenario we would actually have accomplished the very opposite of what we intended to do.
I don't completely get this.
Question (1): I assume that the inner blocking receive will be 'called' (i.e. resumed) as soon as one message has arrived in the message queue, right? Is it realistic to assume that in the short time it takes to resume from the inner blocking receive, there would already be a whole bunch of messages waiting in the queue?
Question (2): Also, the worst case scenario is described as a queue with one normal message and a lot of priority messages. Since all the receive clauses are first checked against the first message in the queue, and then against the second message in the queue, ...(source: this book, page 69-70) shouldn't this be: a lot of normal messages with at the end of the queue a priority message?
如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。
绑定邮箱获取回复消息
由于您还没有绑定你的真实邮箱,如果其他用户或者作者回复了您的评论,将不能在第一时间通知您!
发布评论
评论(4)
Erlang 是一种完全并发的语言,没有理由不能同时发送多条消息。 沿着“哦,这很快——其他线程不可能在那么短的时间内做一些冲突的事情”这样的假设本质上与闭上眼睛说“不存在竞争条件这样的事情,有竞争条件”是一样的。没有竞赛条件这样的东西......”
Erlang being a radically concurrent language, there's no reason you couldn't have been sent several messages at the exact same time. Making assumptions along the lines of "Oh, this is fast -- it's so unlikely other threads would do something that conflicts in that little time" is essentially the same thing as closing your eyes and saying "There's no such thing as race conditions, there's no such thing as race conditions..."
关于(1):是否可以做出这个假设取决于您的具体情况。 例如,所有其他进程在向您发送消息之前可能一直在等待某些事情发生。
关于(2):事实上,在我看来,最坏的情况是没有优先消息,因为每次都必须遍历邮箱:“优先消息进来了吗?”
On (1): Whether this assumption can be made depends on details of your situation. For example, all other processes may have been waiting for something to happen before sending you their messages.
On (2): In fact, it seems to me that the worst case would be no priority messages, as the mailbox would have to be traversed every time: "Has a priority message come in yet?"
根据erlang参考手册接收按时间顺序遍历邮箱。 并阻塞直到消息与其中一个子句匹配。
鉴于听起来内部接收将被阻塞,直到它收到匹配的消息。 因此,您实际上可能会在等待非优先级消息时堆积优先级消息,这与您想要的相反。
摆脱这种困境的方法就是在内部接收上抛出一个新的 after 子句。 或者总是在内部接收中匹配。
尽管查看它们的函数,内部子句应该始终匹配,但我猜这就是他们正在谈论的内容。
According to the erlang reference manual receive traverses the mailbox in time order. and blocks till a message matches the one of the clauses.
Given that it sounds like the inner recieve is going to block till it recieves a matching message. Because of this you might actually stack up priority messages while waiting for non-priority messages which is the opposite of what you want.
Too ways out of this predicament are throwing a new after clause on the inner receive. Or always match in the inner recieve.
Although looking at their function the inner clause should always match but I'm guessing this is what they were talking about.
您突出显示的语句只是说,如果您位于阻塞内部接收块中,您可以在高优先级消息之前处理低优先级消息(因为您正在匹配所有内容),这不一定是意图。
这有点边缘情况 - 我发现当您需要某种类型的过滤时,有效地处理消息很重要。 在其他情况下,我还监视了进程队列深度并相应地改变了我的策略。 作为后者的一个示例,一个简单的日志记录 gen_server 类型进程(使用强制转换来发送日志消息)可能会得到备份,因为将日志消息写入磁盘可能比将消息推送到进程慢很多。 如果队列深度太大,我将丢弃通常记录的信息/垃圾邮件类型消息,只处理(写入磁盘)关键消息。
The statement you highlight is simply saying that if you are in the blocking inner receive block you could process a low priority message before a high priority message (because you are matching everything) which is not necessarily the intent.
It's a bit of an edge case - I've found that being efficient at processing the messages when you want some type of filtering is important. In other cases I've also monitored the process queue depth and altered my strategy accordingly. As an example of the latter a simple logging gen_server type process (which used cast to send the log message) could get rather backed up as writing the log messages to disk can be a lot slower than pushing the messages to the process. If the queue depth got too large I would discard the informational/spam type messages that I would normally log and only process (write to disk) the critical ones.