return HttpResponse()
结束,之后我想运行一个gen 2 GC清除操作。
我该如何做到?这种方法是否有意义?
我可以标记那些永远不需要被垃圾回收的对象,以便GC不需要在每个第二代周期中测试它们吗?
当Django服务器相对空闲时,我该如何配置GC进行完整的清除操作?
Python 2.6.6在多个平台上(Windows / Linux)运行。 return HttpResponse()
结束,之后我想运行一个gen 2 GC清除操作。
我该如何做到?这种方法是否有意义?
我可以标记那些永远不需要被垃圾回收的对象,以便GC不需要在每个第二代周期中测试它们吗?
当Django服务器相对空闲时,我该如何配置GC进行完整的清除操作?
Python 2.6.6在多个平台上(Windows / Linux)运行。我们曾经为gunicorn做过类似的事情。根据你使用的wsgi服务器,你需要找到响应之后的正确挂钩点,而不是之前的。Django有一个request_finished
信号,但这个信号仍然是在响应之前。
对于gunicorn,在配置中你需要定义2个方法,如下所示:
def pre_request(worker, req):
# disable gc until end of request
gc.disable()
def post_request(worker, req, environ, resp):
# enable gc after a request
gc.enable()
post_request
在 HTTP 响应发送完成后运行,这是进行垃圾回收非常好的时机。
我认为一种选择是完全禁用垃圾回收,然后像这里建议的那样在请求结束时手动进行回收:垃圾回收机制是如何工作的?
我想你可以在settings.py
文件中禁用GC。
如果您想在每个请求上运行GarbageCollection,我建议开发一些中间件,在process response方法中执行它:
import gc
class GCMiddleware(object):
def process_response(self, request, response):
gc.collect()
return response
另一种选择可能是完全禁用GC,并配置mod_wsgi(或您正在使用的任何其他工具)更频繁地杀死和重启进程。
基于 @milkypostman 的方法,您可以使用 gevent。 您想要每个请求 执行一次 垃圾回收,但是 @milkypostman 的建议存在问题,即调用 gc.collect() 仍会阻塞请求的返回。 Gevent 让我们能够立即返回并在进程返回后执行 GC。
首先,在您的 wsgi 文件中确保使用 gevent 魔法内容修补全部并禁用垃圾回收。 您可以设置 gc.disable()
,但某些库具有上下文管理器,在禁用它后将其打开(例如 messagepack),因此 0 阈值更加粘性。
import gc
from gevent import monkey
# Disable garbage collection runs
gc.set_threshold(0)
# Apply gevent monkey magic
monkey.patch_all()
然后像这样为Django创建一些中间件:
from gc import collect
import gevent
class BaseMiddleware:
def __init__(self, get_response):
self.get_response = get_response
class GcCollectMiddleware(BaseMiddleware):
"""Middleware which performs a non-blocking gc.collect()"""
def __call__(self, request):
response = self.get_response(request)
gevent.spawn(collect)
return response
您会发现与先前建议的方法相比,主要区别在于gc.collect()
被包裹在gevent.spawn
中,这将不会阻止返回HttpResponse
,从而使您的用户获得更快的响应!
// turn off GC
// do stuff
resp = HttpResponse()
// turn on GC
return resp
我不确定,但是你可以尝试使用// spawn thread to turn on GC in 0.1 sec
代替//turn on GC
。
为了确保GC在请求处理之后才发生,如果线程创建不起作用,你需要修改django本身或使用某种django钩子,正如dcurtis所建议的那样。
如果你正在处理性能关键代码,你可能还想考虑使用像C/C++这样的手动内存管理语言来处理该部分,并仅使用Python来调用/查询它。