Найти - Пользователи
Полная версия: Большое потребление памяти. Не понятное поведение кэширования.
Начало » Django » Большое потребление памяти. Не понятное поведение кэширования.
1 2
JOHN_16
Django 1.3.1, Создан проект, все настройки стандартные, запускается через manae.py, в settings.py добавлено:
DEBUG = False

# отключение системы кэширования
CACHES = {
'default': { 'BACKEND': 'django.core.cache.backends.dummy.DummyCache' }
}
В функции представления запрашиваются данные из БД (около 126к записей), эмитируется какая то работа с ними ( в примере просто подсчитывается длина получаемого списка).
# -*- codung: utf-8 -*-

from django.template import Template, Context
from django.http import HttpResponse

import sqlite3

def main(request):
t=Template(u"""<html>
<head>
<meta content-equip="Content-Type" content="text/html; charset=UTF-8">
</head>

<body>
status {{status}}
</body>
</html>
""")

conn=sqlite3.connect('db.sqlite')
cur=conn.cursor()
data=cur.execute('SELECT * from "ftp.kamchatka.ru" WHERE size>1024 AND size<5368709120').fetchall()
cur.close()
conn.close()

len_data=len(data)

html=t.render(Context({'status': 'ok, length = %s'%len_data}))

return HttpResponse(html)
Проблема в том что процесс займет память в 75мб после выполнения всех процедур, хотя , кажется, не должен этого делать. Сперва я думал что это из за кеширования в память - поправил settings.py, но положение не поменялось.
Я предполагаю что полученный список data, после выхода из функции должен быть уничтожен сборщиком мусора и нигде более не сохраняться, но по видимому это не так.
Количество ссылок на объект списка равно двум, что согласно мануалу, нормально. Пробовал вставлять в код del data - результат тот же.

Откуда берутся эти мб и как от них избавится?
kmike
GC освобождает память не сразу. Можно попробовать запустить сборщик руками после того, как данные обработаны (перед “html = …”), чтоб проверить, в этом ли тут дело:

import gc
gc.collect()
Андрей Светлов
Вставить gc.collect(), например. С другой стороны не понимаю, почему это вас волнует. Вот если бы память постоянно росла….
JOHN_16
kmike
Ах да, забыл упомянуть, кончено же срау же попробовал в ручную вызвать уборщика,но ничего не поменялось, правил код так:
    data=None
import gc
gc.collect()

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

Вот такие плюшки… У кого еще какие идеи есть?
slav0nic
разве это не нормальное поведение интерпретатора, забирать память, и не отдавать её? Она по-моему резервируется и освобождается не сразу
http://effbot.org/pyfaq/why-doesnt-python-release-the-memory-when-i-delete-a-large-object.htm
JOHN_16
И что, получается у меня , как у программиста , нету действительно контроля за ресурсами памяти? что ж это за язык программирования такой который не выполняет своих функций.
На самом деле пребываю в легком шоке…и что это никак не исправить? никаких принудительных вызовов по освобождению памяти?
Как вообще в таком случае на Питоне можно серьезные проекты писать?если он потребление памяти не может контролировать…
kmike
А память точно не VIRT остается, а RSS?

Это поведение не нормальное, можно попробовать с помощью heapy из http://pypi.python.org/pypi/guppy/ посмотреть, какие объекты память занимают.
JOHN_16
kmike по ссылке чет пока не получается запустить штуку, поэтому только так вот своего рода поэтапный анализ происходящего:
F   UID   PID  PPID PRI  NI    VSZ   RSS WCHAN  STAT TTY        TIME COMMAND
0 1000 2226 2225 20 0 23252 11816 - Sl+ pts/11 0:00 /usr/bin/python ./manage.py runserver # запустили джанго приложения
0 1000 2226 2225 20 0 131528 119800 - Sl+ pts/11 0:01 /usr/bin/python ./manage.py runserver # получили data как результат запроса из бд
0 1000 2226 2225 20 0 65360 53720 - Rl+ pts/11 0:01 /usr/bin/python ./manage.py runserver # удалили переменную data (del data)
0 1000 2226 2225 20 0 64060 52420 - Sl+ pts/11 0:01 /usr/bin/python ./manage.py runserver # вызвали очистку сборщиком мусора (gc.collect())
0 1000 2226 2225 20 0 64060 52420 - Sl+ pts/11 0:01 /usr/bin/python ./manage.py runserver # вернули страницу браузеру

Еще для сравнения проанализируем этот обычный Python код (для win и linux платформ результат одинаков)
import gc
# first mark here

d=range(int(1e7))
# second mark here

del d
# third mark here

gc.collect()
# four mark here

Вот расходование памяти RSS:
4360
162500
123464
4492

Таким образом, можно предположить что вручную вызванный сборщик мусора все таки очищает память?
kmike
Возможно, память осталась не от этого запроса К БД, а просто подгрузились какие-то изначально неподгруженные части django или sqlite.

Память дальше-то растет, если то же самое повторить? А если сначала запросить другую страницу (без предполагаемой “дырки”), а потом с “дыркой”, то как себя все поведет?
slav0nic
10 раз повторяю, это нормальное поведение, повтори запрос и увидишь, что озу не стало в 2 раза больше и это не memory leak

мне лень искать, но гуглится на тему
сделай x = range(100000);del x; будет тот же “прикол”

я так понимаю, это заморочки pymalloc

тут в другом вопрос, нахрена ты делаешь fetchall(), чтоб вывести count()? и зачем тебе всё сразу читать в память
This is a "lo-fi" version of our main content. To view the full version with more information, formatting and images, please click here.
Powered by DjangoBB