Portál AbcLinuxu, 30. dubna 2025 10:18
Dnešný blog bude o použití heapy na hľadanie memory leakov v python wsgi aplikácii.
Profiler heapy je súčasťou balíka guppy. Nainštalovať sa dá štandardne cez pypi (pip install guppy
).
Tutoriálov k heapy na internete moc nie je, jeden z mála ako-tak použiteľných je tu. Ukážka použitia heapy:
from guppy import hpy hp = hpy() # inicializácia aplikácie hp.setrelheap() kriticka_cast() heap = hp.heap() print(heap)
Middleware je funkcia (alebo funkcionálny objekt) s parametrami environ (prostredie nastavené webserverom, okrem iného obsahuje query string a požadovanú cestu) a start_response (funkcia ktorá sa musí zavolať pred vrátením generátora).
Riadenie som zabezpečil GET parametrami debugmem_relheap
(nastavenie referenčnej hodnoty heapu, po zavolaní bude zapisovať rozdiely voči tejto hodnote), debugmem_live
(zapnutie pdb) a debugmem_dump
(zápis snapshotu do súboru profile.hpy)
# -*- coding: utf-8 -*- from guppy import hpy from .wsgi import application class StatsMiddleware(object): def __init__(self, app): super(StatsMiddleware, self).__init__() self.app = app self.hp = hpy() def start_ok_response(self, start_response): status = '200 OK' response_headers = [('Content-type', 'text/plain')] start_response(status, response_headers) def __call__(self, environ, start_response): if 'debugmem_dump' in environ.get('QUERY_STRING', ''): heap = self.hp.heap() heap.dump('profile.hpy') # heap_response = [ # '\nHeap\n', # str(heap), # '\nrcs\n', # str(heap.byrcs), # '\nrcs[0]\n', # str(heap.byrcs[0].byid), # '\nrp\n', # str(heap.get_rp()), # '\nModules\n', # str(heap.bymodule), # ] self.start_ok_response(start_response) # for item in heap_response: # yield item elif 'debugmem_live' in environ.get('QUERY_STRING', ''): heap = self.hp.heap() self.start_ok_response(start_response) import pdb pdb.set_trace() elif 'debugmem_relheap' in environ.get('QUERY_STRING', ''): self.hp.setrelheap() self.start_ok_response(start_response) else: for item in self.app(environ, start_response): yield item application = StatsMiddleware(application)
Po obalení vlastnej wsgi alikácie do middlewaru je možné ovládať profiler pomocou GET parametrov. Zvyčajný postup je:
?debugmem_relheap
)?debugmem_dump
pre uloženie, alebo ?debugmem_live
pre preskúmanie v interaktívnom shelliPre ukladanie profilu v určených intervaloch je možné použiť jednoduchý skript (použitie ./skript http://adresa/):
#!/bin/bash ADDRESS=$1 REPEAT_COUNT=10 curl "${ADDRESS}" > /dev/null curl "${ADDRESS}?debugmem_relheap" while true do for i in `seq $REPEAT_COUNT` do curl "${ADDRESS}" > /dev/null done curl "${ADDRESS}?debugmem_dump" done
Zobraziť graf je možné cez integrovaný prehliadač heapy:
from guppy import hpy hp = hpy() hp.pb('profile.hpy')
Pre prepnutie aplikácie do debuggeru pdb stačí zavolať url s parametrom ?debugmem_live
. Aktuálne štatistiky s v lokálnej premennej heap:
(Pdb) heap Partition of a set of 189233 objects. Total size = 27139464 bytes. Index Count % Size % Cumulative % Kind (class / dict of class) 0 72048 38 6146088 23 6146088 23 str 1 48920 26 4136056 15 10282144 38 tuple 2 10719 6 2580752 10 12862896 47 unicode 3 2383 1 1796200 7 14659096 54 dict (no owner) 4 13848 7 1661760 6 16320856 60 function 5 661 0 1615096 6 17935952 66 dict of module 6 12111 6 1550208 6 19486160 72 types.CodeType 7 1557 1 1415928 5 20902088 77 dict of type 8 1557 1 1406488 5 22308576 82 type 9 2313 1 331656 1 22640232 83 list <702 more rows. Type e.g. '_.more' to view.> (Pdb) heap.byrcs Partition of a set of 189233 objects. Total size = 27140232 bytes. Index Count % Size % Cumulative % Referrers by Kind (class / dict of class) 0 65049 34 5867160 22 5867160 22 types.CodeType 1 16121 9 1903488 7 7770648 29 function 2 23610 12 1809464 7 9580112 35 tuple 3 5071 3 1709360 6 11289472 42 type 4 4407 2 1655128 6 12944600 48 function, tuple 5 12880 7 1585352 6 14529952 54 dict of type 6 7195 4 1553200 6 16083152 59 dict of module 7 465 0 1217688 4 17300840 64 function, module 8 10607 6 792688 3 18093528 67 dict (no owner) 9 2665 1 555704 2 18649232 69 dict of module, tuple <2579 more rows. Type e.g. '_.more' to view.> (Pdb) heap[5].byrcs Partition of a set of 661 objects. Total size = 1615096 bytes. Index Count % Size % Cumulative % Referrers by Kind (class / dict of class) 0 464 70 1216640 75 1216640 75 function, module 1 179 27 342728 21 1559368 97 module 2 15 2 38760 2 1598128 99 function, module, types.FrameType 3 1 0 12568 1 1610696 100 dict (no owner), dict of email.LazyImporter, dict of module, guppy.heapy.heapyc.RootStateType, module, types.FrameType 4 1 0 3352 0 1614048 100 guppy.heapy.heapyc.RootStateType, module 5 1 0 1048 0 1615096 100 module, types.FrameType
Tiskni
Sdílej:
Hmm, zaujímavé, dali by sa napísať nejaké detaily (chápem, že niektorí ľudia majú zmluvne zakázané hovoriť o produkte, ja som o tomto tiež nesmel hovoriť kým nebol produkt hotový).
Je to aplikace na predni panel zesilovace. Vicemene to ovlada pres seriovy port ridici desku, ktera prepina a nastavuje ruzne elektronicke potenciometry a spinace/relatka (tzn. digitalne ovladany analog). Ridici deska navic meri ruzna mista v zesilovaci (napr. napajecky, vystupni napeti/proudy atd.) a tim dela realtime diagnostiku jak zesilovace, tak reproduktoru. Vsechny tyhle veci jsou pristupny pres network client/server. Ta QML aplikace je vlastne jen klient k ty siti. Je to napsane hodne v QML/JS, jen ta sitova cast je v C++ (pristupna v QML pres Q_PROPERTY a Q_INVOKABLE). Bezi to pres EGLFS primo nad framebufferem, ale je tam jadro 2.6.35, ktere asi jeste ma problem s tickama (kdyz jsem zvysil na 1000Hz, vsechno se zlepsilo).
This page was unable to display a Google Maps element. The provided Google API key is invalid or this site is not authorized to use it. Error Code: InvalidKeyOrUnauthorizedURLMapError
Nie som autorom webu. Ja som robil len webové konfiguračné rozhranie pre zariadenie a dotykové UI v QML ;)
Neviem ako inde, ale môjho zamestnávateľa by asi dosť trápilo keby kvôli nejakej drobnosti ako zabudnuté vyčistenie cache dochádzalo na serveri k OOM.
V tomto počasí neberiem s humorom nič. Najradšej by som vonku behal nahý s plameňometom, ale je mi na to moc teplo.
Mne tu ukazuje teplomer hnusných 24.6°C (po všetkých opatreniach okrem klimatizácie ktoré ma napadli vrátane obalenia časti domu na ktúrú svieti slnko alobalom [a áno vyzerá to úplne nahovno]).
ISSN 1214-1267, (c) 1999-2007 Stickfish s.r.o.