面向 Ray 开发者的调试#

本调试指南面向 Ray 项目的贡献者。

在调试器中启动进程#

当进程崩溃时,在调试器中启动它们通常很有用。Ray 目前允许进程在以下工具中启动:

  • valgrind

  • the valgrind profiler

  • the perftools profiler

  • gdb

  • tmux

要使用这些工具中的任何一个,请确保首先在你的机器上安装了它们(已知在 MacOS 上使用 gdbvalgrind 会有问题)。然后,你可以通过添加环境变量 RAY_{PROCESS_NAME}_{DEBUGGER}=1 来启动一部分 Ray 进程。例如,如果你想在 valgrind 中启动 raylet,你只需要设置环境变量 RAY_RAYLET_VALGRIND=1

要在 gdb 中启动进程,该进程也必须在 tmux 中启动。因此,如果你想在 gdb 中启动 raylet,你需要使用以下方式启动你的 Python 脚本:

RAY_RAYLET_GDB=1 RAY_RAYLET_TMUX=1 python

然后你可以使用 tmux ls 列出 tmux 会话,并连接到相应的会话。

你还可以获取 raylet 进程的 core dump 文件,这在提交 问题 时特别有用。获取 core dump 的过程取决于操作系统,但通常需要在启动 Ray 之前运行 ulimit -c unlimited 以允许写入 core dump 文件。

后端日志记录#

raylet 进程记录了关于任务执行和节点间对象传输等事件的详细信息。要在运行时设置日志级别,可以在启动 Ray 之前设置 RAY_BACKEND_LOG_LEVEL 环境变量。例如,你可以执行:

export RAY_BACKEND_LOG_LEVEL=debug
ray start

这将把源代码中所有 RAY_LOG(DEBUG) 行打印到 raylet.err 文件中,你可以在日志记录和调试中找到该文件。如果设置成功,你应该在 raylet.err 的第一行看到:

logging.cc:270: Set ray log level from environment variable RAY_BACKEND_LOG_LEVEL to -1

(在 logging.h 中,-1 被定义为 RayLogLevel::DEBUG。)

class StackTrace {
  DEBUG = -1,

后端事件统计#

如果设置了 RAY_event_stats=1 环境变量,raylet 进程还会定期将事件统计信息倾倒到 debug_state.txt 日志文件中。要同时启用定期将统计信息打印到日志文件,你可以额外设置 RAY_event_stats_print_interval_ms=1000

事件统计包括 ASIO 事件处理程序、定期计时器和 RPC 处理程序。以下是事件统计的示例:

Event stats:
Global stats: 739128 total (27 active)
Queueing time: mean = 47.402 ms, max = 1372.219 s, min = -0.000 s, total = 35035.892 s
Execution time:  mean = 36.943 us, total = 27.306 s
Handler stats:
  ClientConnection.async_read.ReadBufferAsync - 241173 total (19 active), CPU time: mean = 9.999 us, total = 2.411 s
  ObjectManager.ObjectAdded - 61215 total (0 active), CPU time: mean = 43.953 us, total = 2.691 s
  CoreWorkerService.grpc_client.AddObjectLocationOwner - 61204 total (0 active), CPU time: mean = 3.860 us, total = 236.231 ms
  CoreWorkerService.grpc_client.GetObjectLocationsOwner - 51333 total (0 active), CPU time: mean = 25.166 us, total = 1.292 s
  ObjectManager.ObjectDeleted - 43188 total (0 active), CPU time: mean = 26.017 us, total = 1.124 s
  CoreWorkerService.grpc_client.RemoveObjectLocationOwner - 43177 total (0 active), CPU time: mean = 2.368 us, total = 102.252 ms
  NodeManagerService.grpc_server.PinObjectIDs - 40000 total (0 active), CPU time: mean = 194.860 us, total = 7.794 s

回调延迟注入#

有时,bug 是由 RPC 问题引起的,例如,由于某些请求的延迟,系统进入死锁。为了调试和重现此类问题,我们需要一种方法来为 RPC 请求注入延迟。为此,引入了 RAY_testing_asio_delay_us。如果你想让某些 RPC 请求的回调在一段时间后执行,可以使用此变量来实现。例如:

RAY_testing_asio_delay_us="NodeManagerService.grpc_client.PrepareBundleResources=2000000:2000000" ray start --head

语法为 RAY_testing_asio_delay_us="method1=min_us:max_us,method2=min_us:max_us"。条目之间用逗号分隔。有一个特殊方法 *,表示所有方法。它的优先级低于其他条目。