Portál AbcLinuxu, 30. dubna 2025 14:00
Pythoní attach-to-process pohodlněji
27.11.2015 23:30
| Přečteno: 1342×
| programování
|
| poslední úprava: 27.11.2015 23:58
Největší nedostatek pythonu z hlediska programátora jsem považoval absenci připojení k běžícímu procesu, pokud nebyl předtím nastartován v debuggeru. Před pár lety jsem na to našel hack a nedávno jsem zjistil, že jeho podobu implementovali do PyCharm IDE, kde to jde teď na pár kliknutí.
Je to už 6 let, co jsem psal návod, jak ohackovat Python přes gdb a dostat funkcionalitu známou jako attach-to-process z gdb. PyCharm to umí a má to implementováno dost podobným hackem, taky přes gdb. Jenže pro programátora mnohem pohodlněji, protože je to integrováno jako featura IDE. I v komunitní free verzi.
PyCharm vs můj starý hack
Hlavní rozdíl je, že se člověk nemusí starat o debug symboly. A implementace je o poznání složitější. GDB musí mít zabudovanou podporu pythonu, přes něj se pythoní proces interně ovládá. K tomu je potřebná knihovna závislá na platformě/architektuře. Přímo podporují x86/amd64, ale k dispozici jsou zdrojáky, takže by to šlo nejspíš použít i na jinou architekturu (pro nějaké embedded věci jako Raspberry Pi). Kombinaci remote debugger + attach-to-process jsem ještě nezkoušel, protože remote debugger je jenom v placené verzi - ale teoreticky by to asi mohlo fungovat.
Oproti mé staré metodě používá jiný způsob zabezpečení konzistentního stavu interpreteru - přes PyGILState_Ensure a PyGILState_Release. Pravděpodobně je to korektnější než můj původní hack. Pak se použije trik s PyRun_SimpleString, případně interní trasovací funkce _PYDEVD_ExecWithGILSetSysStrace.
Musím říct, že z funkcionality jsem příjemně překvapen. Asi jedinou chybu na kráse, co jsem zatím našel je, že po použití attach-to-process a odpojení od procesu mi ten proces nešel zabít bez SIGKILL.
Memory profiling s injekcemi
Nový největší nedostatek je místo původního chybějícího attach-to-process neexistence rozumného memory profileru pro python. Především pokud je potřeba z nějakého několik dní běžícího procesu vydumpovat stav objektů v alokátoru. O vizualizaci škoda mluvit, objgraph sice funguje, ale jeho použitelnost je dost slabá. Hlavně pokud těch objektů máte několik miliard. Podobně RunSnakeMem.
Jediné, co jsem v dané situaci považoval za marginálně použitelné, je meliae. V repozitářích se vyskuje, bohužel na druhé straně to taky už vypadá na mrtvý projekt. S gdb hackem lze statistiku udělat takhle (běžícího procesu, jinak nepotřebujete GDB):
# Stary hack s breaknutim uvnitr VM, viz puvodni zapisek
define breakvm
tbreak ceval.c:1099
end
define meliae_dump
breakvm
continue
call PyRun_SimpleString("from meliae import scanner; scanner.dump_all_objects('/tmp/meliae_dump.json')")
end
V GDB nebo přes GDB machine interface pak stačí zadat meliae_dump. Statistiku vypíšeme následovně:
from meliae import loader
om = loader.load('/tmp/meliae_dump.json')
s = om.summarize()
print s
Příklad výstupu (na jedné staré GUI aplikaci, co jsem měl zrovna po ruce):
Total 188023 objects, 654 types, Total size = 36.4MiB (38211601 bytes)
Index Count % Size % Cum Max Kind
0 4211 2 8094536 21 21 3146008 dict
1 3342 1 7016535 18 39 2097152 numpy.ndarray
2 50560 26 5511918 14 53 19388 str
3 51086 27 4423192 11 65 3040 tuple
4 366 0 1662048 4 69 49488 module
5 1237 0 1375544 3 73 1112 Path
6 9534 5 1144080 2 76 120 function
7 9016 4 1081920 2 79 120 code
8 778 0 703312 1 81 904 type
9 686 0 642096 1 82 936 PyQt4.QtCore.pyqtWrapperType
10 180 0 614880 1 84 3416 Line2D
11 529 0 482448 1 85 912 sip.enumtype
12 2259 1 472160 1 86 36992 list
13 134 0 457744 1 88 3416 Text
14 15621 8 374904 0 89 24 sip.methoddescriptor
15 3898 2 311840 0 89 80 wrapper_descriptor
16 3222 1 283536 0 90 88 weakref
17 9871 5 236904 0 91 24 float
18 594 0 209088 0 91 352 WeakKeyDictionary
19 138 0 153456 0 92 1112 Distribution
Vedlejší efekty meliae injekce
Samotný kód meliae způsobí, že procesu ještě vzroste používaná RAM (RSS) a to značně (řádově klidně 25-50%). Před použitím tam musí být rezerva. Když už proces swapuje, je pozdě. Nebo si počkáte.
Dumpy paměti celkem trvají a výsledkem je dost velký soubor, řádově jsem se pohyboval asi tolik GB, kolik měl sledovaný proces. Mnoho malých objektů. Po načtení a zpracování statistiky lze očekávat, že to spolkne asi tolik paměti, kolik měl soubor na disku.
S pydev gdb helper knihovnou z PyCharm by to šlo skombinovat lépe, aby to bylo přenositelnější, ale zatím jsem to nepotřeboval.
Tiskni
Sdílej:
Komentáře
Vložit další komentář
ISSN 1214-1267, (c) 1999-2007 Stickfish s.r.o.