Евгений Степанищев

Я — эксперт в области разработки веб-приложений и безопасности в интернете. Каждый месяц мой блог посещают около 90 тысяч человек. Работаю техническим директором в «Системах документооборота», занимаюсь электронным правительством.

libmapi: насколько всё запущено

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

Однако к MAPI это отношения не имеет
Цитата из книги «Основы MAPI» Ирвинг де ла Круз, Лес Талер, вырванная из контекста.
5 комментариев
9 апреля 2009 19:44

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

Как я уже не раз говорил, libmapi нещадно течёт. Я сейчас работаю с версией из транка, 921-й комит, это довольно старая версия (текущий коммит — 1303), но утечки находят до сих пор и впереди их немало. Память течёт быстро и при получении больших объёмов данных утекает раньше, чем данные удаётся получить.

Поэтому я изолирую libmapi в отдельном процессе, получаю данные, пока могу и отдаю их «наверх» — родителю, потом делаю новый процесс и получаю следующую пачку. Для того, чтобы отдать данные родителю я использую os.pipe, а данные туда можно передавать только строкой. Так как данные у меня сложные, я их сериализую при помощи cPickle, а для сериализации нужна память.

Где взять память, если всё, что было доступно процессу, съела libmapi? Я пытался выделать память при помощи list(range(20 * 1024 * 1024)), а перед сериализацией удалять, но это не работало. Сегодня я узнал почему. Оказывается Python до версии 2.5 никогда не освобождает память. У меня как раз Python 2.4, приехали.

P.S. Чтобы предотвратить вопросы для чего я делаю list(range(…)), расскажу сразу: для совместимости с Python 3.0, на который мы все когда-нибудь перейдём. Там range возвращает итератор.

Добавлено позднее.

Я сейчас немного поисследовал, сделал замеры и выяснил, что если обращаться к аллокатору памяти Python напрямую (например, через ctypes), то память возвращается:
from ctypes import *

mem = pythonapi.PyMem_Malloc(c_size_t(100*1024*1024))

pythonapi.PyMem_Free(mem)
Комментировать
9 апреля 2009 14:02