Zobrazit předchozí téma :: Zobrazit následující téma |
Autor |
Zpráva |
mar
Založen: 16. 06. 2012 Příspěvky: 608
|
Zaslal: 28. listopad 2014, 02:27:50 Předmět: smart pointery |
|
|
Docela by mě zajímal názor ostatních na smart pointery (strong a weak) pro automatický management paměti pomocí reference countování.
Na jednu stranu mají nespornou výhodu, že se až tak nemusím starat o lifetime objektů,
ale samozřejmě mají i nevýhody:
- relativně pomalé přiřazení (i přes použití atomických operací)
- nafukování binárky
- pokud udělám dlouhý singly-linked list pomocí strong pointerů a uvolním head,
dojde stack a ... (toto by šlo možná vyřešit vláknem, které by řešilo fyzickou destrukci objektů přes queue/ring buffer, ale nevím, jestli by to vůbec stálo za to se o něco takového pokoušet - radši se podobným konstrukcím vyhnout)
- zatíží překladač oproti čistým (raw) pointerům
- weak pointer se musí před dereferencí zamknout (=zkonvertovat na strong pointer).
Oproti tomu nevýhoda u raw pointerů je, že ručně musím řešit lifetime a přesně vyřešit situace, kdy a jakým způsobem řešit fyzické uvolnění a objekty, které na něj ještě mohou držet reference.
Myslím, že při opatrném návrhu by to mohlo jít, ale určitě by se to neobešlo bez extra logiky navíc. Je to ještě jedna z možností, kterou ještě zvažuji.
Momentálně si pohrávám s myšlenkou použít intruzivní countery (pomocí base class) a vzhledem k tomu,
že mám vlastní heap, tak při dosažení nuly u strong ref countu volám destruktor a shrinknu blok, takže v paměti zůstanou pouze
2 countery dokud neklesne weak count na nulu (každý lock weak pointeru se interně nuluje, pokud je neplatný, tj. snižuje weak count).
Fyzicky je velikost těchto intruzivních smart pointerů stejná, jako u raw pointeru (tedy 4 resp. 8 bytů v 64-bit režimu).
Nafouknutí objektu je vždy 8 bytů (případně 8 + vtable ptr), protože nepočítám, že může v praxi zároveň ukazovat na jeden objekt víc než 4G pointerů.
Dřív jsem používal jiný mechanismus, kdy každý objekt měl doubly-linked list pointerů, které na něj ukazují a explicitně při mazání objektu se vynulovaly všechny pointery, které na něj ukazovaly.
Toto mělo nevýhodu hlavně v tom, že velikost takto spravovaného pointeru byla 3x větší a že ani teoreticky nepřipadala v úvahu možnost, aby to běželo ve více vláknech
(což mě u entit netrápilo).
Výhoda ale byla, že jsem vůbec nemusel řešit strong vs weak reference.
O GC jsem uvažoval ze začátku, ale nakonec jsem tuto možnost zavrhl (nemám rád GC z mnoha důvodů, primárně proto, že nemám přehled, kolik paměti v daný moment skutečně používám
a taky proto, že se mi nechtělo psát state of the art GC, protože naivní implementace nepřipadala v úvahu).
Asi bych to uzavřel tím, že všelék na správu paměti prostě neexistuje (resp. o zádném nevím |
|
Návrat nahoru |
|
|
Vilem Otte
Založen: 18. 09. 2007 Příspěvky: 462 Bydliště: Znojmo - Sedlesovice, Kravi Hora
|
Zaslal: 28. listopad 2014, 05:45:31 Předmět: |
|
|
Uff... já bych řekl jak na co - někde je super je použít, někde je to peklo - prostě použij to co se ti víc hodí.
Já dávám přednost řešit vše manuálně (abych si hlídal kde mi co utíká, napsal jsem si vlastní alokátory/delokátory, kdy jim můžeš přihazovat různé parametry (jejich jméno, velikost alokace, apod.) - hodí se to - a pomáhá to, hlavně nepotřebuješ být v debug módu, jen napsat jeden define navíc).
Naprosto souhlasím se závěrem, univerzální způsob správy paměti neexistuje. _________________ Should array indices start at 0 or 1? My compromise of 0.5 was rejected without, I thought, proper consideration. |
|
Návrat nahoru |
|
|
OndraSej
Založen: 28. 07. 2007 Příspěvky: 767 Bydliště: Brandýs nad Labem
|
Zaslal: 28. listopad 2014, 06:30:26 Předmět: |
|
|
Taky hodne zalezi na tom, o jaky smart pointer jde... std::unique_ptr<> ma nulovy overhead a stoji za to ho pouzivat (resp. nepouzivat ho nestoji za cas straveny pri hledani leaku). S move semantikou v C++11 to je navic dobry zpusob jak v kodu dokumentovat (a vynucovat korektnost) predavani vlastnictvi objektu.
Pokud jde o pocitani referenci, tak je tu jeste jeden vecny s cyklickymi referencemi... a s tim, ze co do spotreby casu na tom jsou (muzou byt) stejne spatne nebo hur nez dobry GC.
Btw. linked list je (nezavisle na kontextu a na problemu) skoro jiste spatne reseni kvuli CPU cache, nejen kvuli stack overflow. _________________ http://trionteam.net |
|
Návrat nahoru |
|
|
pcmaster
Založen: 28. 07. 2007 Příspěvky: 1824
|
Zaslal: 28. listopad 2014, 11:30:00 Předmět: |
|
|
Velke firmy mavaju vlastne verzie, ktore su velmi podobne std, ale maju rozne vychytavky ako rozne politiky pre weak_ptr pre rozne single-threaded a multi-threaded, kazdopadne kazdemu rozhodne 100% doporucujem hlavne unique_ptr okamzite zacat pouzivat, ak to situacia umoznuje.
Pri navrhu vlastnych pozor prave na cache, napr. aby refcounter bol blizko pri samotnych datach, aby to vliezlo do 1 cache line, inak to bude uplne peklo na vykon. Ako je to u std netusim, ale snad nie su blbi.
Podla mna bezpecnost a cistota kodu s tymito krasnymi C++ veciami masivne prevysuje nejaky strach o vykon... premature optimisation? Ked tak zapuzdrit a az v pripade, ze sa ukaze, ze na nich viazne vykon, si to prepisat vlastnymi.
Velmi zaujimava prednaska, ktora sa tomuto venuje, bola tento rok na CppCon:
https://www.youtube.com/watch?v=Qq_WaiwzOtI
asi okolo 21. minuty zacina analyzovat shared_ptr. A mozno pride aj goto _________________ Off-topic flame-war addict since the very beginning. Registered since Oct. 2003!
Interproductum fimi omne est. |
|
Návrat nahoru |
|
|
OndraSej
Založen: 28. 07. 2007 Příspěvky: 767 Bydliště: Brandýs nad Labem
|
|
Návrat nahoru |
|
|
mar
Založen: 16. 06. 2012 Příspěvky: 608
|
Zaslal: 28. listopad 2014, 19:07:03 Předmět: |
|
|
Díky za odpovědi, myslím, že intruzivní smart pointery budou nakonec přece jen ok. Ještě popřemýšlím o těch nonatomic (single threaded) pointerech, bude to chtít asi nějaký stress test.
OndraSej: ty ses těch linked listů nějak chytil
Linked list jsem nezmiňoval proto, že bych jej považoval za výhru, ale proto, že je to jedna možnost, kdy refcounting vybouchne (tj. dlouchý jednosměrný chain).
Co se týká ostatních kontejnerů, std::list a std::map jsou z mého pohledu prakticky k ničemu.
Co se týká hashmap, myslím, že jsme v jednom threadu s quasem názorně předvedli, že jednoduchá custom implementace může být rychlejší , než std::unordered_map.
Navíc třeba na Linuxu s gcc a jejich libstdc++ je implementace ~2x pomalejší, než u Windows/msc (což mě velmi překvapilo).
Mimochodem toto je dobrý důvod, proč "vynalézat kolo", obzvlášť když to tvoje kolo pak jede všude stejně rychle
Ohledně sortování malých bloků: nejrychlejší je insertion sort a ne bubble sort, jak zmiňuje v té přednášce. |
|
Návrat nahoru |
|
|
rezna
Založen: 27. 07. 2007 Příspěvky: 2156
|
Zaslal: 28. listopad 2014, 19:57:38 Předmět: |
|
|
mar napsal: |
Mimochodem toto je dobrý důvod, proč "vynalézat kolo", obzvlášť když to tvoje kolo pak jede všude stejně rychle |
Neni to dobry duvod. Je to jak zminil pcmaster premature optimalizace. Az se opravdu prokaze, ze dany kontejner na danem miste je pomaly a nevhodny pak je cas na to "vynalezat kolo", do te doby je to zbytecne spalenej cas, ktery jsi mohl venovat lepsimu navrhu aplikace nebo jine funkcionalite ... |
|
Návrat nahoru |
|
|
mar
Založen: 16. 06. 2012 Příspěvky: 608
|
Zaslal: 28. listopad 2014, 20:28:05 Předmět: |
|
|
rezna napsal: |
Neni to dobry duvod. Je to jak zminil pcmaster premature optimalizace. Az se opravdu prokaze, ze dany kontejner na danem miste je pomaly a nevhodny pak je cas na to "vynalezat kolo" |
Pokud mi něco na jiné platformě a stejném hw bezdůvodně běží 2x pomaleji, je to pro mě víc než pádný důvod |
|
Návrat nahoru |
|
|
quas4
Založen: 18. 10. 2007 Příspěvky: 199
|
Zaslal: 29. listopad 2014, 13:23:05 Předmět: Re: smart pointery |
|
|
mar napsal: |
Docela by mě zajímal názor ostatních na smart pointery (strong a weak) pro automatický management paměti pomocí reference countování. |
nepouzivam a ani nepotrebuji. Kdyz neco alokuji tak se ujistim ze to i dealokuji ve chvili kdy uz to neni potreba. Smart pointery generuji cache-line overhead ktery neni na prvni pohled videt ale muze mit vyrazny dopad na rychlost. A hledani leaku v kodu ktery pouziva smart pointery je vyrazne komplikovanejsi. |
|
Návrat nahoru |
|
|
perry
Založen: 28. 07. 2009 Příspěvky: 879
|
Zaslal: 29. listopad 2014, 15:35:04 Předmět: |
|
|
Já používám raw pointery a vlastní memory alokátor. Na konci běhu programu ho celý zlikviduji a to co jsem zapomněl případně ručně uvolnit se uvolní. Samozřejmě v případě, že někdě nepokazím něco jiného. _________________ Perry.cz |
|
Návrat nahoru |
|
|
Ladis
Založen: 18. 09. 2007 Příspěvky: 1536 Bydliště: u Prahy
|
Zaslal: 29. listopad 2014, 16:02:35 Předmět: |
|
|
Tak on by to po tobě uvolnil OS, kdybys to neuvolnil. |
|
Návrat nahoru |
|
|
perry
Založen: 28. 07. 2009 Příspěvky: 879
|
Zaslal: 29. listopad 2014, 17:15:51 Předmět: |
|
|
Tak ono nejenom po skončení programu, ale třeba i celý level nakonci vysypu a resetnu memory manager. _________________ Perry.cz |
|
Návrat nahoru |
|
|
mar
Založen: 16. 06. 2012 Příspěvky: 608
|
Zaslal: 29. listopad 2014, 17:15:54 Předmět: |
|
|
No, pořád ještě váhám
raw pointery mají kromě jiného výhodu, že zbytečně nezatěžují překladač.
Momentálně mám intruzivní refcount, ve 32-bit režimu to je 4 byty overhead na refcountovaný objekt (2 16-bitové countery) a 8 bytů v 64-bit režimu, což by mělo být vůči cache relativně ok.
Každá instance smart pointeru zabírá stejně jako raw pointer.
Samozřejmě nehodlám smart pointery cpát úplně všude.
Klasický problém, který mě napadá, je tento: jsou dvě entity A a B. Entita A má target pointer na B (typický kandidát na weak pointer). B smažu.
Napadá mě spousta možností, jak toto vyřešit bez smart pointerů, ale nic mi nepřipadá dostatečně elegantní... |
|
Návrat nahoru |
|
|
Ladis
Založen: 18. 09. 2007 Příspěvky: 1536 Bydliště: u Prahy
|
Zaslal: 29. listopad 2014, 19:20:02 Předmět: |
|
|
perry napsal: |
Tak ono nejenom po skončení programu, ale třeba i celý level nakonci vysypu a resetnu memory manager. |
To jsi předtím neřek, ale jinak to je přesně ono, co mně stačí - mít jistotu, že po skončení levelu uvolním všechno (i když - nebo právě proto - že to jsou různě provázaná data). Moje první hra a třeba, co si pamatuju, Atomic Bomberman to nedělaly. V té mé hře to bylo jedno, prostě kvůli tomu s každým levelem bylo nižší FPS, ale levely byly jen 4. U toho Bombermana jsem ale holt musel jednou za čas hru ukončit a znovu spustit . |
|
Návrat nahoru |
|
|
OndraSej
Založen: 28. 07. 2007 Příspěvky: 767 Bydliště: Brandýs nad Labem
|
Zaslal: 29. listopad 2014, 19:48:41 Předmět: |
|
|
mar> zatez prekladace je nejaky problem? Ty smart pointery IMO nezmeni skoro nic a usetreny cas prekladu je (ve srovnani s casem na ladeni problemu s pameti) zanedbatelny.
Pokud chces optimalizovat cas prekladu, tak bys mel popremyslet o zmene jazyka
Jinak souhlasim s reznou, pokud jde o predcasnou optimalizaci. Imo spravny postup je
(1) zprovoznit to,
(2) zprovoznit to tak, aby to fungovalo vzydy spravne,
(3) pokud to nefunguje dostatecne rychle, zoptimalizovat to. _________________ http://trionteam.net |
|
Návrat nahoru |
|
|
|