为什么在实现 GenServer 时跟踪#Reference 比跟踪#PID 更好?
Why it would be better keeping track of #Reference than #PID when implementing a GenServer?
Elixir 的 Mix and OTP Guide Chapter GenServer 解释了如何使用 GenServer
.
实现注册服务器托管代理
每个代理的 PID 都保存在一个映射中,其中键是客户端提供的代理名称,值是代理的 PID。
为了避免保留对死代理的引用,该指南建议使用 Process.monitor/1
监控新创建的代理,并通过添加名为 refs
的新映射稍微修改状态,其中包含引用(值Process.monitor/1
) 作为键返回,代理的名字作为值返回。它还显示了如何使用 handle_info/2
来处理监视消息以更新 refs
.
Process.monitor/1
接收一个 PID(例如 #PID<0.66.0>
)作为参数,returns 接收一个参考(例如 #Reference<0.0.0.551>
)。 handle_info/2
捕获的 :DOWN
消息提供了 PID 和引用。
因为我们一直都知道这两个值:与在 refs
中使用 PID 相比,使用引用作为键有什么好处?
这是一个一致性问题。虽然您只监视进程,但没有区别。但是底层 :erlang.monitor/2
不能监控 只有 个进程:有端口等,基本上没有 PID
.
来自文档:
• Object
The monitored entity, which triggered the event. When monitoring a local process or port, Object
will be equal to the pid()
or port()
that was being monitored. When monitoring process or port by name, Object
will have format {RegisteredName, Node}
where RegisteredName
is the name which has been used with monitor/2
call and Node
is local or remote node name (for ports monitored by name, Node
is always local node name).
总结:Reference
是一个实体,被监控。它可能是一个进程,一个端口,等等。虽然您不想 demonitor/1
关闭端口的整个过程被监视,但您应该使用引用。
如果您只有一个小项目并且只想监视一些进程,那么只记住 PID 就可以了。但我建议使用 Reference,因为项目增长很快,您可能不仅要监控流程。 Elixir 在 :erlang.monitor/2
下面使用,它还可以让你监控 Erlang 单调时间和 Erlang 系统时间之间的 ports
和 time_offset
。这可以在 Docs here 中找到。参考更通用,一般来说使用参考是更好的做法。
这里举个小例子我想说的是:
iex(1)> :erlang.monitor(:time_offset, :clock_service)
#Reference<0.0.3.100>
iex(2)> :erlang.monitor(:process ,self())
#Reference<0.0.3.113>
Elixir 的 Mix and OTP Guide Chapter GenServer 解释了如何使用 GenServer
.
每个代理的 PID 都保存在一个映射中,其中键是客户端提供的代理名称,值是代理的 PID。
为了避免保留对死代理的引用,该指南建议使用 Process.monitor/1
监控新创建的代理,并通过添加名为 refs
的新映射稍微修改状态,其中包含引用(值Process.monitor/1
) 作为键返回,代理的名字作为值返回。它还显示了如何使用 handle_info/2
来处理监视消息以更新 refs
.
Process.monitor/1
接收一个 PID(例如 #PID<0.66.0>
)作为参数,returns 接收一个参考(例如 #Reference<0.0.0.551>
)。 handle_info/2
捕获的 :DOWN
消息提供了 PID 和引用。
因为我们一直都知道这两个值:与在 refs
中使用 PID 相比,使用引用作为键有什么好处?
这是一个一致性问题。虽然您只监视进程,但没有区别。但是底层 :erlang.monitor/2
不能监控 只有 个进程:有端口等,基本上没有 PID
.
来自文档:
•
Object
The monitored entity, which triggered the event. When monitoring a local process or port,
Object
will be equal to thepid()
orport()
that was being monitored. When monitoring process or port by name,Object
will have format{RegisteredName, Node}
whereRegisteredName
is the name which has been used withmonitor/2
call andNode
is local or remote node name (for ports monitored by name,Node
is always local node name).
总结:Reference
是一个实体,被监控。它可能是一个进程,一个端口,等等。虽然您不想 demonitor/1
关闭端口的整个过程被监视,但您应该使用引用。
如果您只有一个小项目并且只想监视一些进程,那么只记住 PID 就可以了。但我建议使用 Reference,因为项目增长很快,您可能不仅要监控流程。 Elixir 在 :erlang.monitor/2
下面使用,它还可以让你监控 Erlang 单调时间和 Erlang 系统时间之间的 ports
和 time_offset
。这可以在 Docs here 中找到。参考更通用,一般来说使用参考是更好的做法。
这里举个小例子我想说的是:
iex(1)> :erlang.monitor(:time_offset, :clock_service)
#Reference<0.0.3.100>
iex(2)> :erlang.monitor(:process ,self())
#Reference<0.0.3.113>