Erlang:gen_server 还是我自己的自定义服务器?

发布于 2024-08-12 22:05:55 字数 746 浏览 7 评论 0原文

我需要编写一个服务器,它将接收来自其他模块的指令,并根据收到的指令采取行动。效率是我最关心的问题。那么我是使用 gen_server 还是编写自己的服务器。我所说的“我自己的服务器”的意思是这样的:

-module(myserver).
-export([start/0, loop/0]).

start() ->
        spawn(myserver, loop, []).

loop() ->
   receive
        {From, Msg} -> %Do some action here... ;
        message2 -> %Do some action here...;
        message3 -> %Do some action here...;
        message4 -> %Do some action here...;
        .
        .
        .
        _-> ok
   end,
   loop().

因此,要使用myserver,我可能会在启动进程时以注册名称注册该进程,然后每个客户端都会使用此 pid 向服务器发送消息。

那么我应该使用这种方法,还是使用 gen_server 行为来实现服务器?使用 gen_server 有什么优势吗?但是与 myserver 相比,使用 gen_server 会增加任何开销吗?

I need to write a server that will receive instructions from other modules and take actions depending on the instructions received. Efficiency is my main concern. So do I use gen_server or do I write my own server. By "my own server" I mean something like:

-module(myserver).
-export([start/0, loop/0]).

start() ->
        spawn(myserver, loop, []).

loop() ->
   receive
        {From, Msg} -> %Do some action here... ;
        message2 -> %Do some action here...;
        message3 -> %Do some action here...;
        message4 -> %Do some action here...;
        .
        .
        .
        _-> ok
   end,
   loop().

So to use myserver, I will probably register the process under a registered name while starting it, and then each client will send messages to the server using this pid.

So should I use this method, or instead implement the server using the gen_server behaviour? Are there any advantages to using gen_server? But will using gen_server add any overhead, when compared to myserver?

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(5

倚栏听风 2024-08-19 22:05:55

与自行实现的服务器相比,gen_server 的开销可以忽略不计,因为它需要对每条消息进行一些额外的函数调用(其中一个是动态的)。我认为您不应该在实施时考虑这一点。您是否在任何时候改变了主意,从 gen_server 迁移到您自己的服务器应该很简单。

与简单循环相比,使用 gen_server 可以获得的是:

  • 调试(使用 sys)
  • SASL 日志记录
  • 休眠支持
  • 代码升级支持

gen_server will have a negligible overhead compared to self-implemented servers, because it requires a few additional function calls per message (one of which is dynamic). I don't think you should consider this at this point of implementation. Did you changed your mind at any point, moving from gen_server to your own server should be straightforward.

What you get with gen_server compared to a simple loop is:

  • debugging (with sys)
  • SASL logging
  • hibernation support
  • code upgrade support
山色无中 2024-08-19 22:05:55

我也会选择gen_server。一旦您使用过该设施,您就会学会欣赏它的价值。函数回调可能有点尴尬(例如用于异步调用的handle_cast),但最终您会习惯它。

此外,建议我在没有进行一些测试的情况下不要进行“过早优化”。您可能不想为了边际效率提升而牺牲可读性/可维护性。

I would go with gen_server as well. Once you've used this facility, you will learn to appreciate its value. The function callback can be a bit awkward (e.g. handle_cast for async calls) but in the end, you'll get used to it.

Furthermore, I would be advised not to engage in "premature optimization" without having done some testing. You probably don't want to sacrifice readibility/maintainability for marginal efficiency gains.

千纸鹤 2024-08-19 22:05:55

我会选择 gen_server 只是因为我们花了很多心思让它在各种情况下都能做正确的事情。它负责处理难以正确处理的细节。我想 gen_server 可能会增加一些开销,但我已经停止提供性能建议。如果您真的感兴趣,那么就实现两者并测量速度,这是找出答案的唯一可靠方法。

I would go with the gen_server simply because so much thought has gone into making it do the right thing under various circumstances. It takes care of details that are difficult to get right. I imagine gen_server might add some overhead but I've stopped giving performance advice. If you're really interested then implement both and measure the speed, that's the only surefire way to find out.

永不分离 2024-08-19 22:05:55

您还可以使用 RabbitMQ 背后的人员提供的 gen_server2

它类似于 gen_server,除了以下调整(来自评论):

1) the module name is gen_server2

2) more efficient handling of selective receives in callbacks
gen_server2 processes drain their message queue into an internal
buffer before invoking any callback module functions. Messages are
dequeued from the buffer for processing. Thus the effective message
queue of a gen_server2 process is the concatenation of the internal
buffer and the real message queue.
As a result of the draining, any selective receive invoked inside a
callback is less likely to have to scan a large message queue.

3) gen_server2:cast is guaranteed to be order-preserving
The original code could reorder messages when communicating with a
process on a remote node that was not currently connected.

You can also use gen_server2 by the guys behind RabbitMQ.

It's like gen_server except for the following adjustments (from the comments):

1) the module name is gen_server2

2) more efficient handling of selective receives in callbacks
gen_server2 processes drain their message queue into an internal
buffer before invoking any callback module functions. Messages are
dequeued from the buffer for processing. Thus the effective message
queue of a gen_server2 process is the concatenation of the internal
buffer and the real message queue.
As a result of the draining, any selective receive invoked inside a
callback is less likely to have to scan a large message queue.

3) gen_server2:cast is guaranteed to be order-preserving
The original code could reorder messages when communicating with a
process on a remote node that was not currently connected.
北城孤痞 2024-08-19 22:05:55

我从你的问题假设你正在编写一个更“永久”的服务器。

一般来说,如果你做得对的话,滚动你自己的服务器会更通用并且更快一点。但是,这是一个但是:

  • 您必须自己做所有事情,这会增加出错的风险!

  • 如果您希望以 OTP 方式管理您的服务器(如果您正在构建一个强大的系统,您可能会这样做),那么您也必须自己处理所有这些事情。并做到正确。

如果我正在做一个永久服务器,我会开始使用gen_server,只有当我在实现我需要的东西时遇到严重困难时才会回退并推出我自己的服务器。

寿命短的服务器是另一回事。

I assume from your question that you are writing a more "permanent" server.

In general rolling your own server is more versatile and a little faster, if you get it right. But, and this is a big BUT:

  • You will have to do everything yourself, which increases the risk of errors!

  • If you want your server to be managed in the OTP way, which you probably do if you are building a robust system, then you will have to handle all that yourself as well. And get it right.

If I was doing a permanent server I would start out using gen_server and only fallback and roll my own if I run into serious difficulties in implementing what I need.

Short lived servers are another matter.

~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文