0

我对几乎所有东西都使用 python 程序:

  • 部署脚本
  • nagios 例程
  • 网站后端(web2py)

我这样做的原因是因为我可以重用代码来提供不同类型的服务。

不久前,我注意到这些脚本给我的服务器带来了很高的 CPU 负载。我已经采取了几个步骤来缓解这种情况:

  • 后期初始化,使用cached_property(参见此处此处),以便真正初始化那些需要的对象(包括import相关模块)
  • 将我的一些脚本转换为 http 服务(通过简单的web.py实现,包装我的类)。然后通过简单的curl调用触发服务(例如通过 nagios)。

这大大减少了负载,从超过 20 个 CPU 负载降低到远低于 1 个。对于具有大量相互依赖关系的复杂程序,python 启动似乎非常耗费资源。

我想知道这里的人们正在实施哪些其他策略来提高 python 软件的性能。

4

1 回答 1

3

一个简单的一次性改进是使用PyPy而不是标准 CPython 用于长期脚本和守护程序(对于短期脚本,它不太可能有帮助,实际上可能有更长的启动时间)。除此之外,听起来您已经发现了短期系统脚本的最大改进之一,即避免为频繁调用的脚本启动 Python 解释器的开销。

例如,如果您从另一个脚本调用一个脚本并且它们都在 Python 中,那么您绝对应该考虑将另一个脚本作为模块导入并直接调用其函数,而不是使用subprocess或类似的方法。

我明白这并不总是可以做到这一点,因为一些用例依赖于被调用的外部脚本——例如,Nagios 检查将很难始终保持驻留。您使实际检查脚本成为简单 HTTP 请求的方法似乎足够合理,但我采取的方法是使用被动检查并运行外部服务来定期更新状态。这允许生成检查结果的服务作为守护进程驻留,而不需要 Nagios 为每次检查调用脚本。

另外,请注意您的系统,看看缓慢是否真的是 CPU 过载或 IO 问题。您可以使用实用程序vmstat来查看您的 IO 使用情况。如果您受 IO 限制,那么优化您的代码不一定会有很大帮助。在这种情况下,如果您正在处理诸如处理大量文本文件(例如日志文件)之类的事情,那么您可以将它们压缩存储并使用 Python 的gzip模块直接访问它们。这增加了 CPU 负载但减少了 IO 负载,因为您只需要从磁盘传输压缩数据。您还可以使用相同的方法直接以 gzip 格式编写输出文件。

具体恐怕我不是特别熟悉web2py,但是如果数据的新鲜度不是很关键,你可以研究一下是否容易在前面放一个缓存层。尝试并确保您的服务器和客户端都正确使用条件请求,这将减少请求处理时间。如果他们使用的是后端数据库,您可以调查memcached之类的东西是否会有所帮助。只有当您遇到相当多的请求或每个请求的处理成本很高时,这些措施才可能给您带来真正的好处。

我还应该补充一点,通常以其他方式减少系统负载有时会带来令人惊讶的好处。我曾经有一个运行 Apache 的相对较小的服务器,我发现迁移到 nginx 的帮助非常大——我相信它在一定程度上提高了请求处理的效率,但主要是它释放了一些内存,然后文件系统缓存可以用来进一步提高 IO-绑定操作。

最后,如果开销仍然是一个问题,那么仔细分析您最昂贵的脚本并优化热点。这可能是在改进您的 Python 代码,或者如果您愿意,也可能意味着将代码推送到 C 扩展。通过将数据路径代码推送到 C 扩展中以进行大规模日志处理和类似任务(一次谈论数百 GB 的日志),我获得了一些出色的性能。但是,这是一种繁重且耗时的方法,应该保留给您真正需要速度提升的少数地方。这还取决于您是否有足够熟悉 C 的人来做这件事。

于 2013-06-07T13:23:35.967 回答