amarao_san

Чудное

Сегодня у нас сработал алерт на free memory на сервере с exabgp. Она съела 25Гб памяти и собиралась есть дальше со скоростью 200Мб/ч. Проблему аккуратно предотвратили, но у меня на развлечении осталась остановленная (нет bgp, нет апдейтов) копия exabgp, с res в 25.7Гб. Инспекция coredump показала, что там всего 1.8Гб строк. Вопрос со строками возник потому, что после прекращения внешней активности exabgp продолжила логгирование с разной скоростью (от нескольких сообщений в секунду до нескольких десятков тысяч), сама ротируя свой лог.

Так вот, во-первых в корке логов было менее 1.8Гб, а во-вторых, после того, как за три часа она таки сказала всё, что думает, память легче не стала.

У меня остался процесс на сервере и я сейчас с ним играюсь.

В процессе отладки родилась идея: подцепиться дебаггером и посмотреть все объекты.

print(sum([o.__sizeof__() for o in gc.get_objects()]))

Оно споткнулось на TypeError: descriptor '__sizeof__' of 'object' object needs an argument

Я полез отлаживать однострочник в обычный питон и обнаружил, что оно ломается на объекте типа cell (type, repr, dir и o.__sizeof__()):

<type 'cell'>

<cell at 0x7f1bc4d200f8: str object at 0x7f1bc4e26260>

['__class__', '__cmp__', '__delattr__', '__doc__', '__format__', '__getattribute__', '__hash__', '__init__', '__new__', '__reduce__', '__reduce_ex__', '__repr__', '__setattr__', '__sizeof__', '__str__', '__subclasshook__', 'cell_contents']

Traceback (most recent call last):

  File "<stdin>", line 5, in <module>

AttributeError: 'cell' object has no attribute '__size__'

Я полез читать про них. Нашёл. https://docs.python.org/2.7/c-api/cell.html

У меня внезапный вопрос: а как его получить в свой namespace (я про type('cell')) в свой namespace?

У него нет __module__, и как он появляется в самом питоне никто не может сказать. Зато с ним развлечений много. его o.__class__ говорит, что нельзя создавать объекты типа cell, и другие забавные глюки.

Интроспекция тупит. Пока что я придумал — просто пропускать такие. Но их оказалось множество. Например, банальный type (type(type)).

Так что пришлось писать многострочник. Что делать в gdb крайне неудобно. Так что пришлось писать модуль аварийной интроспекции объектов.

import gc

def sum_all():

    result = 0

    for obj in gc.get_objects():

        try:

            result += obj.__sizeof__()

        except Exception:

            pass

    return result


И результат прикольный. 1362200 байт. Не похоже на 25 Гб.

Я решил проверить это на реальном питоне. К сожалению, слишком много объектов уворачиваются. 

Я поэксперментировал на ipython в junyper — там sum_all сказало около 7Мб. Я сделал массив из 100000 элементов — счётчик вырос на мегабайт. Похоже.

Теперь вопрос: чем я могу посмотреть память между «gc» и /proc/self/maps? Я хочу понять, куда всё делось.


Error

default userpic

Your IP address will be recorded 

When you submit the form an invisible reCAPTCHA check will be performed.
You must follow the Privacy Policy and Google Terms of use.