139

我的内存使用量随着时间的推移而增加,并且重新启动 Django 对用户不利。

我不确定如何分析内存使用情况,但一些关于如何开始测量的提示会很有用。

我有一种感觉,有一些简单的步骤可以产生巨大的收益。确保“调试”设置为“假”显然是一件大事。

任何人都可以建议其他人吗?在低流量站点上缓存会有多大改进?

在这种情况下,我使用 mod_python 在 Apache 2.x 下运行。我听说 mod_wsgi 有点精简,但在这个阶段切换会很棘手,除非我知道收益会很大。

编辑:感谢到目前为止的提示。有什么建议如何发现内存用尽了吗?是否有 Python 内存分析的指南?

另外如前所述,有一些事情会使切换到 mod_wsgi 变得很棘手,所以我想在朝着这个方向前进之前对我可以期待的收益有所了解。

编辑: Carl 在这里发布了一个更详细的回复,值得一读:Django Deployment:Cutting Apache's Overhead

编辑: Graham Dumpleton 的文章是我在 MPM 和 mod_wsgi 相关内容上找到的最好的文章。我相当失望的是,没有人可以提供任何有关调试应用程序本身内存使用情况的信息。

最终编辑:嗯,我一直在与 Webfaction 讨论这个问题,看看他们是否可以帮助重新编译 Apache,这是他们对此事的看法:

“我真的认为切换到 MPM Worker + mod_wsgi 设置不会给您带来太多好处。我估计您可能能够节省大约 20MB,但可能不会更多。”

所以!这让我回到了我最初的问题(我仍然对此一无所知)。如何确定问题所在?这是一个众所周知的格言,没有测试就不会优化,看看你需要优化的地方,但是关于测量 Python 内存使用的教程很少,而且根本没有特定于 Django。

感谢大家的帮助,但我认为这个问题仍然悬而未决!

另一个最终编辑;-)

我在 django-users 列表上问了这个问题,得到了一些非常有用的回复

老实说最后一次更新!

这是刚刚发布的。可能是最好的解决方案:Profiling Django object size and memory usage with Pympler

4

10 回答 10

50

确保您没有保留对数据的全局引用。这可以防止 python 垃圾收集器释放内存。

不要使用mod_python. 它在 apache 中加载一个解释器。如果您需要使用 apache,请mod_wsgi改用。切换并不难。这很容易。为 django 配置比 Brain-deadmod_wsgi更容易。mod_python

如果您可以从您的要求中删除 apache,那对您的记忆会更好。spawning似乎是运行 python web 应用程序的新的快速可扩展方式。

编辑:我不明白切换到 mod_wsgi 是多么“棘手”。这应该是一项非常容易的任务。请详细说明您在使用交换机时遇到的问题。

于 2009-01-28T11:11:14.943 回答
28

如果您在 mod_wsgi 下运行,并且由于它与 WSGI 兼容而可能正在生成,您可以使用Dozer查看您的内存使用情况。

在 mod_wsgi 下,只需在 WSGI 脚本的底部添加:

from dozer import Dozer
application = Dozer(application)

然后将浏览器指向http://domain/_dozer/index以查看所有内存分配的列表。

我还将添加我对 mod_wsgi 的支持的声音。与 mod_python 相比,它在性能和内存使用方面有着天壤之别。Graham Dumpleton 对 mod_wsgi 的支持非常出色,无论是在积极开发方面还是在帮助邮件列表中的人们优化他们的安装方面。curse.com的David Cramer发布了一些图表(不幸的是,我现在似乎找不到)显示他们在那个高流量站点上切换到 mod_wsgi 后 cpu 和内存使用量急剧下降。一些 django 开发人员已经切换。说真的,这很容易:)

于 2009-02-01T20:18:57.733 回答
15

这些是我知道的 Python 内存分析器解决方案(与 Django 无关):

免责声明:我持有后者的股份。

单个项目的文档应该让您了解如何使用这些工具来分析 Python 应用程序的内存行为。

以下是一个不错的“战争故事”,也提供了一些有用的指示:

于 2009-02-06T19:55:59.537 回答
5

此外,请检查您是否不使用任何已知的泄密者。众所周知,由于 unicode 处理中的错误,MySQLdb 会在 Django 中泄漏大量内存。除此之外,Django Debug Toolbar可能会帮助您跟踪猪。

于 2009-02-04T21:22:05.030 回答
4

除了不保留对大型数据对象的全局引用之外,尽量避免将大型数据集加载到内存中。

在守护进程模式下切换到 mod_wsgi,并使用 Apache 的 worker mpm 而不是 prefork。后一步可以让您以更少的内存开销为更多的并发用户提供服务。

于 2009-01-28T16:13:18.190 回答
4

Webfaction 实际上有一些降低 django 内存使用率的技巧

要点:

  • 确保 debug 设置为 false(你已经知道了)。
  • 在您的 apache 配置中使用“ServerLimit”
  • 检查内存中没有加载大对象
  • 考虑在单独的进程或服务器中提供静态内容。
  • 在您的 apache 配置中使用“MaxRequestsPerChild”
  • 找出并了解您正在使用多少内存
于 2009-02-01T03:15:41.403 回答
3

mod_wsgi 的另一个优点:在指令中设置一个maximum-requests参数WSGIDaemonProcess,mod_wsgi 将每隔一段时间重新启动守护进程。除了第一次遇到新进程时页面加载缓慢之外,用户应该没有明显的影响,因为它将把 Django 和您的应用程序代码加载到内存中。

但即使您确实有内存泄漏,也应该防止进程大小变得太大,而不必中断对用户的服务。

于 2009-01-30T20:23:11.657 回答
3

这是我用于 mod_wsgi 的脚本(称为 wsgi.py,并放在我的 django 项目的根目录中):

import os
import sys
import django.core.handlers.wsgi

from os import path

sys.stdout = open('/dev/null', 'a+')
sys.stderr = open('/dev/null', 'a+')

sys.path.append(path.join(path.dirname(__file__), '..'))

os.environ['DJANGO_SETTINGS_MODULE'] = 'myproject.settings'
application = django.core.handlers.wsgi.WSGIHandler()

根据需要调整 myproject.settings 和路径。我将所有输出重定向到 /dev/null 因为 mod_wsgi 默认情况下会阻止打印。请改用日志记录。

对于阿帕奇:

<VirtualHost *>
   ServerName myhost.com

   ErrorLog /var/log/apache2/error-myhost.log
   CustomLog /var/log/apache2/access-myhost.log common

   DocumentRoot "/var/www"

   WSGIScriptAlias / /path/to/my/wsgi.py

</VirtualHost>

希望这至少可以帮助您设置 mod_wsgi,以便您可以查看它是否有所作为。

于 2009-02-06T07:09:02.347 回答
1

缓存:确保它们被刷新。某些东西很容易进入缓存,但由于缓存引用而永远不会被 GC 处理。

Swig'd 代码:确保正确完成任何内存管理,在 python 中很容易错过这些,尤其是第三方库

监控:如果可以,获取有关内存使用情况和命中的数据。通常你会看到某种类型的请求和内存使用之间的相关性。

于 2009-02-04T04:31:53.260 回答
1

我们偶然发现了 Django 中的一个带有大型站点地图(10.000 个项目)的错误。似乎 Django 在生成站点地图时试图将它们全部加载到内存中:http: //code.djangoproject.com/ticket/11572 - 当 Google 访问该站点时有效地杀死了 apache 进程。

于 2011-01-13T19:37:37.737 回答