Django Python Сборщик мусора горе - PullRequest
6 голосов
/ 04 января 2011

После 2 дней отладки я прибег к своему временному блюду: сборщик мусора Python.
Мое приложение содержит много объектов в памяти.И это хорошо работает.
ГК выполняет обычные раунды (я не играл с пороговыми значениями по умолчанию (700, 10, 10)).
Время от времени, в середине важной транзакции,Развертывание 2-го поколения включается и просматривает мои объекты ~ 1,5M поколения 2.
Это занимает 2 секунды! Номинальная транзакция занимает менее 0,1 секунды.

Мой вопрос: что мне делать?делать?
Я могу отключить развертки поколения 2 (установив очень высокий порог - это правильный путь?), и ГХ послушен.
Когда мне их включать?
Мы внедрили вебс использованием Django, и каждый пользовательский запрос занимает около 0,1 секунды.
Оптимально, я буду запускать эти циклы GC gen 2 между запросами пользовательского API.Но как мне это сделать?
Мой вид заканчивается на return HttpResponse(), ПОСЛЕ , который я хотел бы запустить для сканирования GC 2-го поколения.
Как мне это сделать?Имеет ли этот подход смысл?

Можно ли пометить объект, который НИКОГДА не нужно собирать мусором, чтобы ГХ не проверял их каждый цикл 2-го поколения?
Как настроить ГХ для выполнения полных зачистоккогда сервер Django относительно простаивает?

Python 2.6.6 на нескольких платформах (Windows / Linux).

Ответы [ 4 ]

3 голосов
/ 04 января 2011

Я полагаю, что одним из вариантов будет полное отключение сбора мусора, а затем сбор вручную в конце запроса, как предлагается здесь: Как работает механизм сбора мусора?

Я полагаю, что вы можете отключить GC в вашем файле settings.py.

Если вы хотите запускать GarbageCollection при каждом запросе, я бы предложил разработать промежуточное программное обеспечение, которое делает это в ответе процесса метод:

import gc
class GCMiddleware(object):
    def process_response(self, request, response):
        gc.collect()
        return response
1 голос
/ 26 августа 2016

Мы сделали что-то подобное для 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, и поэтому очень хорошее время для сборки мусора.

1 голос
/ 04 января 2011

Альтернативой может быть полное отключение GC и настройка mod_wsgi (или того, что вы используете) для более частого уничтожения и перезапуска процессов.

0 голосов
/ 04 января 2011

Мое представление заканчивается возвратом HttpResponse (), ПОСЛЕ которого я хотел бы запустить очистку GC 2-го поколения.

// turn off GC
// do stuff
resp = HttpResponse()
// turn on GC
return resp

Я не уверен, но вместо //turn on GC вы можете // spawn thread to turn on GC in 0.1 sec.

Чтобы убедиться, что сборщик мусора не произойдет до тех пор, пока не будет обработан запрос, если порождение потока не сработает, вам нужно изменить сам django или использовать какой-либо хук django, как предложил dcurtis. 1010 *

Если вы имеете дело с критичным к производительности кодом, вам также может потребоваться использовать для этой части язык ручного управления памятью, такой как C / C ++, и использовать Python просто для его вызова / запроса.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...