性能分析


这进阶内容,主要适用于服务器的开发者。

Evennia提供了几种方法可以测试服务器的性能。


简单的计时测试

Python的 timeit 模块对测试小东西很有用。例如,为了测试是使用for循环更快还是使用列表解析更快,你可以使用以下代码:
    import timeit
    # 做1000000次for循环的时间
    timeit.timeit("for i in range(100):\n    a.append(i)", setup="a = []")
   <<< 10.70982813835144
    # 做1000000列表解析的时间
    timeit.timeit("a = [i for i in range(100)]")
   <<<  5.358283996582031
关键字setup用来设置不应包括在时间测试内的东西,如第一个调用中的 a = []。

在默认状态下,timeit函数会运行每个测试100万次,然后给出运行的总时间。但如果测试中包含了数据库写入操作,则可以不使用默认的设置,用关键字number可以指定更少的运行次数。


使用cProfile

Python带有自己的性能分析器,名为cProfile(这是cPython的,目前在pypy中没有这个测试)。由于Evennia进程运行方式的原因,无法用通常的形式启动性能分析器(python -m cProfile evennia.py),而必须使用 game/runner.py。evennia.py 会在服务器启动时调用它(并且会监控服务器的重启和关闭)。runner.py 中带有正确启动性能分析器的设置。
python runner.py --profile-server start
这会启动Evennia,服务器组件会在 cProfile 下运行。你还可以用 --profile-portal 来分析接入程序,但你很少需要这样做。

请注意,在性能分析器运行的时候,你进程所用的内存会大大高于往常,而且会不断增加。所以不要放着它不管,要仔细监控它。

在服务器运行了一段时间之后你需要停止它的运行,让性能分析器可以给出分析报告。不要在任务管理器中终止程序或发送kill信号终止程序,这很可能会弄乱性能分析。可以使用 evennia.py stop,在游戏中使用 @shutdown 会更好。

在服务器关闭之后,你会看到性能分析器创建了一个新文件 game/server.prof。


分析性能

server.prof 是一个二进制文件,有许多方法可以分析、显示其中的内容,以下的方法都只在Linux中测试过(如果你是 Windows / Mac 的用户,请告知我们哪些是可行的)。

我们推荐使用 Runsnake 将不同进程的处理器使用情况以图形化的方式显示出来。想看更详细的使用时间列表,可以使用 KCachegrind。为了让 KCachegrind 能够使用Python的分析文件,你还需要使用包装脚本 pyprof2calltree。你可以通过 pip 获取 pyprof2calltree,但 KCacheGrind 需要通过包管理器或其主页获得。

如何解释、分析性能数据可不是个简单的问题,它取决于你想分析什么。如果你需要帮助,可以在论坛中提问,但你需要提供 server.prof 文件以供比对,并且详细说明文件生成时的确切情况。


模拟玩家

如果游戏中没有玩家,那很难测试游戏的“实际”性能。 Evennia自带有方法可以让模拟的玩家(“机器人”或“傀儡”)登录到你的游戏中。这称为 Dummyrunner 系统,位于 src/utils/dummyrunner/ 中。

dummyrunner 是一个独立的程序,它会生成一些假的玩家,让他们从你定义的任何端口登录到游戏中。登录之后,他们会开始随机执行各种操作。假玩家所模拟的内容都在 src/utils/dummyrunner/dummyrunner_actions.py 中定义。在这个文件中有许多假玩家的配置,可以按你的需要注释掉相关内容。更多信息请见 dummyrunner_actions.py 的头部。设置 definingsettings.DUMMYRUNNER_ACTIONS_MODULE 可以改用你自定义的 dummyrunner_actions 模块。

下面是如何使用dummyrunner:
  1. 请确保不要在正式运行的系统中使用,因为它会在数据库中新建很多垃圾对象。请使用空的数据库或测试数据库。
  2. 请确保所有玩家默认都有建造者权限,可以在 game/settings.py 中加入 PERMISSION_PLAYER_DEFAULT = "Builders"。
  3. 启动Evennia服务器(最后会激活性能分析,见上文)。
  4. 执行 python dummyrunner.py 20,添加20个的玩家。
  5. 使用完毕后用Ctrl-C(在Linux上)终止dummyrunner。

每个模拟玩家都会创建一个新的帐户并登录,每个玩家都会立即建立一个新的房间并移动进去。在那里,他们会按照 dummyrunner_actions 模块中的定义随机行动。这样的连接操作可以让默认的登录位置(默认为虚空)保持清洁。如果你想连接上百个模拟玩家,可能会注意到有延迟发生,这是因为所有玩家都会集中在同一时间创建并登录。通常这并不代表真实的使用情况。

为了检验,默认的Evennia曾测试过多达1000个“正常操作”的模拟玩家。在经历了初始延迟之后(所有玩家在这时建立连接),游戏通常是完全可玩的。要记住,在大多数MUD游戏的真实情况中,永远不会看到有超过20到50个玩家同时在线,你在测试时可以把这一点考虑进去。

总的来说,dummyrunner系统可以对游戏的通用性能做很好的测试,但是实际用户的行为仍是难以模仿的。因此,真实的游戏测试还是必要的。


(原文:https://github.com/evennia/evennia/wiki/Profiling    翻译:卢铱俊)