Django не освобождает память

Основываясь на других сообщениях, я понимаю, что у Django нет проблемы утечки памяти, но у меня есть веб-приложение, в котором при вызове определенной процедуры используется много памяти, но не вся она освобождается после этого. Я не знаю, правильная ли это терминология, но если я отслеживаю mem_used_perc на AWS, вызывая эту процедуру только на веб-странице, я вижу, что использование памяти увеличивается и не возвращается к предыдущим уровням.

Я вызываю рекурсивную процедуру, которая может повторяться до 7 раз. Вот код:

def autosearch(self, phase=1, report="", num = 10): """ Это ЭС-поиск, следующий определенным правилам для определения и заполнения уведомления о результатах поиска """

Есть ли причины, по которым это может вызвать симптомы, которые я наблюдаю, и как это исправить?

Чтобы решить эту проблему, вы можете попробовать вызвать метод gc.collect() в конце функции автопоиска. Это вручную запустит сборщик мусора, который очистит всю неиспользуемую память.

Вы также можете попробовать включить настройку DEBUG в вашем проекте Django, что заставит Django регистрировать все утечки памяти. Для этого добавьте следующую строку в ваш файл settings.py:

DEBUG = True

После включения этой функции вы можете проверить журналы на наличие проблем с утечкой памяти. Вы также можете попробовать использовать профилировщик памяти, чтобы определить конкретные области в вашем коде, где память освобождается неправильно.

Также для оптимизации кода можно попытаться уменьшить количество операторов if, используемых в коде. Например, вместо использования нескольких операторов if для проверки различных условий, вы можете использовать один оператор if с несколькими условиями.

Вот пример:

# Before optimization
if self.care_need_category_residential:
    categories.append("care_residential")
if self.care_need_category_nursing:
    categories.append("care_nursing")
if self.care_need_category_dementia:
    categories.append("care_dementia")
if self.care_need_category_nursing_dementia:
    pass
if self.care_need_category_personal_care:
    categories.append("care_residential")
if self.care_need_category_respite_care:
    categories.append("care_respite")

# After optimization
if (self.care_need_category_residential or self.care_need_category_personal_care):
    categories.append("care_residential")
if self.care_need_category_nursing:
    categories.append("care_nursing")
if self.care_need_category_dementia:
    categories.append("care_dementia")
if self.care_need_category_respite_care:
    categories.append("care_respite")

Похоже, что вы испытываете так называемую "утечку памяти" в вашем приложении Django. Утечка памяти происходит, когда программа постоянно выделяет память для использования, но не освобождает ее для других процессов, когда она больше не нужна. Это может привести к тому, что программа использует чрезмерное количество памяти и может аварийно завершиться.

Для решения этой проблемы важно определить источник утечки памяти и предпринять шаги по его устранению. Это может быть непростой задачей, поскольку утечки памяти могут быть вызваны различными факторами, включая неэффективные алгоритмы, плохое управление памятью и ошибки в коде.

Один из способов определить источник утечки памяти в вашем Django-приложении - использовать профилировщик памяти. Профилировщик памяти - это инструмент, который может помочь вам определить, какие части вашего кода используют больше всего памяти и потенциально вызывают утечку. Определив источник утечки, вы можете предпринять шаги по его устранению, например, оптимизировать алгоритмы, улучшить управление памятью или исправить ошибки в коде.

Другим возможным решением является использование сборщика мусора. Сборщик мусора - это программа, которая автоматически освобождает память, которая больше не используется программой. Это может помочь предотвратить утечку памяти, гарантируя, что память выделяется для использования только тогда, когда она необходима, и освобождается для других процессов, когда она больше не нужна.

Подводя итог, важно определить и устранить источник утечки памяти в вашем Django-приложении, чтобы предотвратить чрезмерное использование памяти и потенциальные сбои. Использование профилировщика памяти и внедрение сборщика мусора может помочь в решении этой проблемы.

Вы уверены, что проблема в том, что память не освобождается? У вас есть проблемы с памятью?

В linux типично, что память продолжает использоваться даже после того, как программа освободила ее снова, поскольку, какая польза от вашей оперативной памяти, если она все время пуста. ОС будет хранить кэшированные данные в оперативной памяти, даже если они не нужны вашему приложению в данный момент, потому что она может выиграть от увеличения производительности, когда позже приложение снова захочет получить эти данные, а они все еще будут в оперативной памяти.

Это называется: кэширование

Я пытался найти документацию по вызову mem_used[_percent] и мне было не совсем понятно, означает ли это используемую память (приложениями + кэш) или память, используемую приложениями. https://docs.aws.amazon.com/AmazonCloudWatch/latest/monitoring/metrics-collected-by-CloudWatch-agent.html

У вас есть проблемы со свободной памятью? На вашем сервере не хватает памяти?

<

Обычно вы можете видеть, как память используется приложением, затем освобождается, но обналичивается операционной системой.

Итак, mem_free снова увеличивается, но он обналичивает память, поэтому mem_cached увеличивается, а mem_used остается прежним.

Это может объяснить то, что вы видите, без утечки памяти.

Например, на моей текущей системе то, что я вижу, когда я делаю cat /proc/meminfo Я почти не вижу свободной памяти, но большая ее часть (68%) занята кэшами, которые будут очищены, как только приложению понадобится память.

   1   │ MemTotal:       16068712 kB
   2   │ MemFree:          178332 kB
   3   │ MemAvailable:   10290764 kB
   4   │ Buffers:          812504 kB
   5   │ Cached:         10203120 kB
   6   │ SwapCached:         1596 kB
   7   │ Active:          4852664 kB
   8   │ Inactive:       10034536 kB

В предоставленном коде нет ничего, что могло бы объяснить утечку памяти.

Проблема должна исходить откуда-то еще (возможно, self.filter_by_budget_range(phase)).

Чаще всего утечки памяти в Django происходят из-за побочных эффектов при использовании объектов, которые создаются при запуске сервера, и которые вы продолжаете кормить новыми данными, даже не осознавая этого, или не зная, что объект привязан к серверу, а не к отдельным запросам.

Например, если у вас есть что-то вроде этого:

class Foobar(models.Model):
    ...
    baz = ""
    ...

    def barfoo(self, baz):
        ...
        self.baz += baz
        ...

Для каждого запроса, в котором вы вызываете obj.barfoo(some_string), Foo.baz будет расти до тех пор, пока сервер не будет перезапущен.

Подобным образом, в следующем примере:

def foobar(baz=[]):
    ...
    baz.append(something)
    ...

Где функция foobar создается один раз при запуске сервера. Каждый раз, когда вы вызываете foobar() с аргументом по умолчанию, baz продолжает расти, пока сервер не будет перезапущен.

Эти два примера, конечно, глупы, это просто чтобы показать простые случаи побочных эффектов, влияющих на память.


Другая возможная проблема может возникнуть, если вы кэшируете некоторые материалы, используя бэкенд, основанный на памяти, например Memcached.


Если вы не знаете, что это может быть, то лучше всего попытаться воспроизвести проблему в разработке и использовать pdb (или даже django-pdb) для проверки памяти, либо во время работы сервера разработки, либо непосредственно в оболочке (что может быть более удобно, если вы можете воспроизвести в оболочке).

Вернуться на верх