Debugging 什么';从进程id识别进程标识的最佳erlang方法是什么?

Debugging 什么';从进程id识别进程标识的最佳erlang方法是什么?,debugging,erlang,process,ets,process-dictionary,Debugging,Erlang,Process,Ets,Process Dictionary,在调试时,我通常会查看大约5000个进程,每个进程可能是大约100个gen_服务器、FSM等中的一个。如果我想知道erlang进程是什么,我可以做: process_info(pid(0,1,0), initial_call). 得到如下结果: {initial_call,{proc_lib,init_p,5}} …这几乎是无用的 最近,我突然想到(振作起来)用一个名字注册每个进程,告诉我这个进程代表谁。例如,player_1150是表示player 1150的player进程。是的,我最终

在调试时,我通常会查看大约5000个进程,每个进程可能是大约100个gen_服务器、FSM等中的一个。如果我想知道erlang进程是什么,我可以做:

process_info(pid(0,1,0), initial_call).
得到如下结果:

{initial_call,{proc_lib,init_p,5}}
…这几乎是无用的

最近,我突然想到(振作起来)用一个名字注册每个进程,告诉我这个进程代表谁。例如,player_1150是表示player 1150的player进程。是的,我最终在一周的时间里制造了几百万个原子。(如果我的系统运行时没有使用大约8GB的实际内存(如果有的话),我很想听到关于将限制提高到10000000个原子的缺点的评论。)这样做意味着我可以在实时系统的控制台上,查询所有进程的消息队列长度,找到最大的违规者,然后检查这些进程是否已注册,并打印出它们注册的atom

我遇到了一个障碍:我正在将进程从一个节点移动到另一个节点。现在一个玩家进程可以有3个不同的名字;播放器_1158,播放器_1158_弃用,播放器_1158_替换。我必须绝对确保我以精确的时间注册和注销这些名称,以确保一个进程始终被命名,并且适当的名称始终存在,并且我不会试图注册某个垂死进程已经拥有的名称。这里有一些slop空间,因为这只用于现场系统的控制台调试。然而,当我开始感觉这种机制影响了我开发系统的方式(移动进程的机制)时,我觉得是时候做点别的了

我现在有两个想法。将进程ID与其描述关联的ets表:

ets:insert(self(), {player, 1158}).
我真的不喜欢那个,因为我必须手动保持桌子干净。当玩家退出(或崩溃)时,有人负责确保其数据从ets表中删除

第二种选择是使用流程字典,存储类似的信息。当我对一个实时系统的探索让我想知道进程是谁时,我可以使用进程信息查看他的进程字典


我意识到这些解决方案在功能上都不干净,但考虑到系统本身从来都不是这些数据的消费者,我并不太担心。我需要某些调试工具来快速轻松地工作,因此所描述的行为不值得讨论。是否有任何令人信服的论据(除了学术上的“不要使用‘这是邪恶的’”罐装垃圾?)我很乐意听到其他建议和它们的理由。

如果您正在调试
genu server
s和
genu fsm
s,而它们仍在运行,我将为这些行为实现
handle\u info
函数。当您向每个进程发送一个
{get_info,ReplyPid}
元组时,相关进程可以发回一个描述其自身状态、状态等的术语。这样,您就不必在进程本身之外跟踪此信息


Isac提到已经有一个

您应该试用,它是一个保存流程元数据的非常方便的应用程序


一个进程可以注册多个名称,并且可以将任意属性与一个进程关联(其中键和值可以是任何erlang术语)。此外,gproc还监视已注册的进程,并在它们崩溃时自动注销它们。

小心动态生成的原子。如果你像player_一样生成原子,你最终会耗尽原子,因为虚拟机从不“垃圾收集”它们。你不妨用这个来获取进程的状态:我没有意识到这样的事情存在,感谢您指出这一点。使用注册表命名进程的动机之一是,使用handle\u info或handle\u cast作为检索此信息的机制,我将无法查询任何已积压消息或正在等待消息的进程(我在这个系统中没有这样做,但这是一个潜在的问题。因为我偶尔需要调试消息队列中充满了cruft的进程,所以按需方法被废弃了。没错!GPROC的完整文档: