netch80: (Default)
[personal profile] netch80
Окружение: Linux/x86-64/glibc

I. Питон.

Берём небольшую тестовую программку:


import os, gc
def ps():
    os.system("ps -p %s -o vsz,rss | tail -n +2" % (os.getpid(),))
class A:
    pass
ps()
a = [A() for x in range(0,3000000)]
ps()
del a; gc.collect()
ps()


Если её запустить под 2.7 в описанном виде, получаем:

 20996  4456
1182596 1161900
936816 920336


Сделав одно небольшое изменение - A наследуется от object (и становится new style class) - получаем:

 20996  4452
314112 293528
 93032 76660


Формально new style легче буквально на десяток байт, но меняется что-то другое. Теперь запустим вообще под python3:

 28872  6956
249692 224164
 28872  7196


Раньше мы меряли потребление памяти тяжёлым процессом по пиковым нагрузкам, но это, как видно, уже неадекватный результат.
Кстати, окончательное освобождение из-под объектов происходит именно при gc.collect(). До этого чистится чуть-чуть (насколько я понял, собственно список, но не объекты).

Но!!! Как только мы создаём не пустой объект, а с реальным содержимым, память перестаёт освобождаться по удалению объектов:(

II. Уже Си (чтобы избавиться от возможных эффектов Питона). Тестовая программа порождает 50 тредов, после каждых 10 рассказывая объём процесса, каждый тред делает malloc(1) и уходит в вечный цикл сна. Запускаем... ой...

  6120   372
743572  2640
1480892 6736
2218212 8972
2365708 13068
2447668 13068


64MB на тред не включая 8MB стека до какого-то порога - это пять. косяков.
Теория см. здесь. И точно:

$ env MALLOC_ARENA_MAX=1 ./t1
  6120   372
612500  4688
694460  4688
776420  4868
858380  4868
940340  5060


А всего-то хотелось соотнести объём процесса с нагрузкой и придумать, как определять, что с ним что-то не так (например. забытый, но не удалённый и не отцеплённый, мусор в памяти). Но, видимо, просто не решится.

Date: 2012-06-14 02:00 pm (UTC)
ext_605364: geg MOPO4 (Default)
From: [identity profile] gegmopo4.livejournal.com
Да, это я и имел в виду.

Можно короче:
sum(int(line.split()[1]) for line in open('/proc/%s/smaps' % (xpid,)) if '_Dirty:' in line)

Или на шелле:
grep _Dirty: /proc/$1/smaps | numsum -c | cut -d' ' -f2

Profile

netch80: (Default)
netch80

January 2026

S M T W T F S
    1 23
45678910
11121314151617
18192021222324
25262728293031

Most Popular Tags

Style Credit

Expand Cut Tags

No cut tags
Page generated Jan. 2nd, 2026 06:24 pm
Powered by Dreamwidth Studios