Zobrazit předchozí téma :: Zobrazit následující téma |
Autor |
Zpráva |
LukeMak
Založen: 08. 02. 2013 Příspěvky: 16
|
Zaslal: 15. červen 2013, 18:57:05 Předmět: Vyjimky (Exceptions) v hernim prumyslu |
|
|
Cau, cetl jsem v knize zamerene na architekturu enginu, kterou napsal byvaly zamestnanec Nauhgty Dog a dalších studii, ze obecne "vypinali" vyjimky a vubec je nepouzivali (hlavne teda prej v Naughty Dog - pri vyvoji na konzole). Dost me to prekvapilo, chapu, ze je tam vyssi rezie, ale nemyslel jsem si, ze vyjimky uplne ignoruji. Pouziti pri realtime renderingu bych taky vyloucil, ale takove chyby jako nepodarilo se nacist nejaky soubor, na to si myslim, ze jsou výjimky fajn... Co si o tom myslite? |
|
Návrat nahoru |
|
 |
perry

Založen: 28. 07. 2009 Příspěvky: 879
|
Zaslal: 15. červen 2013, 19:18:24 Předmět: |
|
|
Osobně výjimky nepoužívám v C/C++ nikde, takže se tomu ani nedivím. Hodně funkcí (hlavně práci se soubory) navíc stačí kontrolovat na návratovou hodnotu, typicky když se něco podělá, vrací NULL. Navíc v renderingu, když se to pokazí výjimkou, která stejně nejde vyřešit, tak jestli to napíše chybu a vypne se to, nebo to rovnou spadne / zatuhne, je celkem jedno.. tak jako tak se to musí pustit znovu. Navíc čas spotřebovaný na případnou kontrolu se nevrátí. Je to tedy můj osobní pohled na věc, nejsem profi game-developer.
PS: Jako v Javě je to věc jiná, tam ty výjimky musím "naprasit" i když nechci. _________________ Perry.cz |
|
Návrat nahoru |
|
 |
Tringi

Založen: 28. 07. 2007 Příspěvky: 290
|
Zaslal: 15. červen 2013, 20:15:45 Předmět: |
|
|
Je to jako se vším, nesmí se to přehánět, s výjimkami obzvláště.
Určitě je vhodné je využít ve spojení s RAII, ale ještě lépe je přehodnotit návrh tak, aby vůbec nemohly vzniknout, příklad: Mám-li RTS a každý vzniknuvší tank alokuju jako objekt, pak musím řešit, co se stane, když dojde paměť. Jakkoliv se může zdát použití velkého, předběžně rezervovaného, pole hloupým, nemusím zmíněný problém řešit a můžu z jeho velikosti rovnou říct hráči, kolik RAM na hru potřebuje. Prakticky vše ostatní (než zajištění zdrojů) se dá řešit logikou lokálně místo výjimkami.
Výjimky taky něco stojí, ale ne až tolik, jak se často démonizuje. GCC/MinGW nedávno přešlo z implementace, která stála nějaké instrukce na každém stack-frame (SJLJ) na implementaci, která je rychlejší ale stojí místo v EXE/paměti na typové tabulky (DWARF2). Výhody SEH implementace (MSVC) z hlavy nevím.
Definitivně ale výjimky nemají co dělat v nejužších herních smyčkách, které se provádí sta-tisíckrát za snímek. _________________ WWW | GitHub | TW |
|
Návrat nahoru |
|
 |
Vilem Otte

Založen: 18. 09. 2007 Příspěvky: 462 Bydliště: Znojmo - Sedlesovice, Kravi Hora
|
Zaslal: 15. červen 2013, 21:16:32 Předmět: |
|
|
Vyjímky nepoužívám, napsat je stojí mnohem více úsilí než klasické asserty (zvláště pokud si upravíte assert ať vám třeba dá výstup do logu).
Přeci jen:
kód: |
try
{
... stuff ...
}
catch
{
... stuff ...
}
finally
{
... stuff ...
} |
Je sakra delší kód než hloupý ale účinný
_________________ Should array indices start at 0 or 1? My compromise of 0.5 was rejected without, I thought, proper consideration. |
|
Návrat nahoru |
|
 |
michalferko
Založen: 29. 09. 2008 Příspěvky: 83
|
Zaslal: 15. červen 2013, 22:12:25 Předmět: |
|
|
Ja vynimky pouzivam iba pri veciach, ktore znamenaju okamzite ukoncenie aplikacie (tj. neskompiluje sa shader, alebo je poskodeny subor). Cize mam v celej aplikacii jeden try-catch blok.
Pokial viem (opravte ma prosim ak trepem), tak vynimky uberaju na vykone az ked nejaka vynimka nastane.
V mojom pripade sa teda stava velmi malokedy ze vynimka nastane, a vacsinou to pouzivam pri debugovani, ale v realnom release aplikacie pravdepodobne vynimka nenastane (pokial mi uzivatel nebude babrat so subormi aplikacie). Vlastne okrem inicializacie aplikacie mi to ani nema prilis kde hodit vynimku.
Beriem to ako vyborne sprehladnenie kodu a netreba riesit navratove hodnoty cez kopu funkcii. Ak to naozaj nie je nutne, tak sa im radsej vyhnem. Neviem si predstavit rozumne pouzitie vynimiek, kde by hrozilo ze nastanu tisicky krat za sekundu. _________________ Moje minihry a ine projekty |
|
Návrat nahoru |
|
 |
OndraSej

Založen: 28. 07. 2007 Příspěvky: 767 Bydliště: Brandýs nad Labem
|
Zaslal: 16. červen 2013, 06:55:31 Předmět: |
|
|
Vilem Otte napsal: |
Vyjímky nepoužívám, napsat je stojí mnohem více úsilí než klasické asserty (zvláště pokud si upravíte assert ať vám třeba dá výstup do logu). |
Tady srovnáváš jablka s hruškama... assert(nepo->aloSeTo()) bys měl srovnávat spíš s if (po->aloSeTo()) throw some_error(), to z hlediska počtu řádek už tak velký rozdíl není. A na rozdíl od jednoduchého assertu ta výjimka jde dál zpracovat přímo v kódu.
Ale zpět k diskuzi - v C++ výjimky používám nerad, ani ne kvůli výkonu, ale spíš kvůli čitelnosti kódu. Výjimka dost výrazně narušuje tok programu a bez pomoci překladače není jasné, jestli volání nějaké funkce může skončit výjimkou, nebo ne.
Pokud se chyby řeší přes návratové hodnoty, je u jejich použití na první pohled vidět, jestli volající chyby ošetřuje, předává dál, nebo ignoruje. A kdy k tomu dojde. A na rozdíl od výjimek je předávání chyb viditelné v každé funkci, přes kterou chyba prochází. S výjimkami bez podrobnějšího zkoumání nebo hodně přesné dokumentace na první pohled často vůbec není jasné, jestli funkce může selhat a pokud ano, tak s jakými výjimkami. S výjimkami kontrolovanými překladačem, jako to má Java, je situace snesitelná, ale kdo tyhle anotace píše... zvlášť když překladače na ně stejně nereagují.
michalferko> pokud výjimka opravdu nastává tisíckrát za vteřinu, tak je používáš špatně Proto to jsou výjimky, aby byly výjimečné. _________________ http://trionteam.net |
|
Návrat nahoru |
|
 |
Krolli
Založen: 12. 05. 2013 Příspěvky: 13
|
Zaslal: 16. červen 2013, 08:15:29 Předmět: |
|
|
OndraSej napsal: |
Ale zpět k diskuzi - v C++ výjimky používám nerad, ani ne kvůli výkonu, ale spíš kvůli čitelnosti kódu. Výjimka dost výrazně narušuje tok programu a bez pomoci překladače není jasné, jestli volání nějaké funkce může skončit výjimkou, nebo ne.
Pokud se chyby řeší přes návratové hodnoty, je u jejich použití na první pohled vidět, jestli volající chyby ošetřuje, předává dál, nebo ignoruje. A kdy k tomu dojde. A na rozdíl od výjimek je předávání chyb viditelné v každé funkci, přes kterou chyba prochází. S výjimkami bez podrobnějšího zkoumání nebo hodně přesné dokumentace na první pohled často vůbec není jasné, jestli funkce může selhat a pokud ano, tak s jakými výjimkami. S výjimkami kontrolovanými překladačem, jako to má Java, je situace snesitelná, ale kdo tyhle anotace píše... zvlášť když překladače na ně stejně nereagují. |
S tymto suhlasim, az na detail ohladom throw anotacie metod/funkcii. Tie anotacie funguju inak ako v Jave a IMHO su nanic. Nekontroluje ich kompilator (nehodi chybu pri preklade ak su nespravne), takze mozu byt out-of-sync s kodom a nikdy nevies, ci si pokryl vsetko (ak nie, popletie to niekoho ineho). Ak tam nejaku vynimku zabudnes uviest a ona vznikne, zavola sa unexpected() a, ak si to nenahradil niecim vlastnym, program spadne. Mozes tam dat throw() (unexpected() pri akejkolvek vynimke) alebo throw(...) (to iste ako keby si tam nedal nic).
Odporucam precitat si A Pragmatic Look at Exception Specifications. Osobne mam ovela radsej navratove hodnoty a zapisovanie do logov. Na druhej strane, raz sa mi stalo, ze mi nejaka metoda hodila UnsupportedException("Multidimensional arrays are supported.") takze sme sa v praci mali na com zabavat.  |
|
Návrat nahoru |
|
 |
Lemik
Založen: 30. 07. 2007 Příspěvky: 138
|
Zaslal: 16. červen 2013, 08:33:24 Předmět: |
|
|
Já tedy začínal "až" s C++, takže žádné FILE*, fopen, fread, fprintf apod. a malloc či free leda s tyčí za neprůstřelným sklem - to rád přenechám alokátorům standardní knihovny... Možná to je proč pro mě mají výjimky smysl.
Výjimky vidím _ne_ jako kontrolu, jestli něco bylo správně provedeno - to nekontroluji. Výjimky jsou pro mě příležitostí a místem k řešení situace, ke které by mohlo dojít. Situaci, kvůli které stejně kontrolujete tu vrácenou hodnotu...
A OndraSej to napsal výstižně - pokud potřebuješ chytat výjimku, která může nastat tisíckrát za vteřinu, děláš to špatně...
LukeMak: Z jakého roku to bylo? Přecijenom před 10 - 5 lety to vypadalo jinak, než teď s C++11. Tedy alespoň pro GCC a porty na různé platformy.
Neznám kompilátory pro konzole, takže pokud někdo ví, jak tam jsou řešené - jestli je má vůbec smysl použít - by mě zajímalo. Otázkou je taky, jestli knihovny třetích stran podporu výjimek mají, což s open source nebo licensed source není problém, zkompiluji si to podle svého, horší to bude pokud je k dispozici jen binárka.
Podstatnějším problémem než samotný overhead pak je, jak OndraSej nastínil, problém nedostatečné (self)dokumentace, jaké že to exceptions volaný kód vlastně může vyhodit. U knihoven třetích stran jsem odkázán na "dobrosrdečnost" vývojářů, že to patřičně zmíní v dokumentaci.
Edit:
Á, Krolli to zmínil ještě přede mnou...
Rozhodně nepoužívat u funkcí throw() specifikaci. Ta je v C++11 deprecated. C++11 naopak přidává noexcept (http://www.stroustrup.com/C++11FAQ.html#noexcept a http://en.cppreference.com/w/cpp/language/noexcept)
Nějaké obecné info k výjimkám:
http://www.parashift.com/c++-faq-lite/exceptions.html
http://www.stroustrup.com/bs_faq2.html#exceptions-why
Edit2: opraveny vyjímky na výjimky
Naposledy upravil Lemik dne 19. červen 2013, 09:36:10, celkově upraveno 1 krát |
|
Návrat nahoru |
|
 |
mar
Založen: 16. 06. 2012 Příspěvky: 610
|
Zaslal: 16. červen 2013, 10:13:39 Předmět: Re: Vyjimky (Exceptions) v hernim prumyslu |
|
|
Výjimky v C++ potenciálně můžou vést k resource leakům - překladač totiž při výjimce automaticky uvolní pouze objekty na zásobníku (C++ nemá GC).
Zadalší overhead není ani tak v rychlosti, ale ve velikosti generovaného kódu (resp. dat). Poslední věc: pokud ladím kód, který háže výjimky, tak se najednou můžu ocitnout jinde, než bych čekal (když to vyletí). Já osobně se bez nich obejdu.
OT: Pokud vím, tak někteří vývojáři nepoužívají ani STL (google např. EASTL) a to ani ne z důvodů rychlosti, ale spíš z důvodu opět velikosti kódu - není to problém na PC, ale na konzolích prý většina velkých her běží tak, že mají volných pár MB a jedou doslova nadoraz (aspoň to tvrdil týpek z Ubisoftu
Taky si pamatuji, že hodně lidí rádo předává objekty hodnotou, což má v C++ opět obrovský overhead na velikost kódu a nakonec i rychlost (i když je reference countovaný), nevím, do jaké míry toto do budoucna vylepší překladač/nový standard, ale já zůstávám u const referencí, kde to jde. |
|
Návrat nahoru |
|
 |
nou

Založen: 28. 07. 2007 Příspěvky: 1050
|
Zaslal: 16. červen 2013, 11:34:16 Předmět: |
|
|
ja osobne som vynimkam tiez nikdy neprisiel na chut. nepouzivanie STL je skor relikt minulosti. kontajnery totiz pouzivaju templaty ktorych podpora nebola v minulosti prave najlepsia. za dalsie kvalita implementacie STL bola casto nizka.
neviem ako moze pouzivanie predavanie konstatntov zvysovat velkost kodu. kopirovaci konstruktor by vo vyslednej binarke mal byt iba raz. overhead je pri predavani hodnotou z toho ked sa musia kopirovat velke objekty z jedneho miesta na druhe. to riesi C++11 ktory prinasa move konstruktor na rychle predavanie hodnotou. _________________ Najjednoduchšie chyby sa najtažšie hľadajú. |
|
Návrat nahoru |
|
 |
mar
Založen: 16. 06. 2012 Příspěvky: 610
|
Zaslal: 16. červen 2013, 12:50:35 Předmět: |
|
|
Tak i když je tam konstruktor jednou, volat se musí A destruktor taky. Plus oba potřebují předat this, kopírovací ještě navíc src. Máš pravdu, mrknu se jak je to s move ctorem, docela mě to zajímá (rvalue reference?). |
|
Návrat nahoru |
|
 |
Vilem Otte

Založen: 18. 09. 2007 Příspěvky: 462 Bydliště: Znojmo - Sedlesovice, Kravi Hora
|
Zaslal: 16. červen 2013, 13:27:14 Předmět: |
|
|
#mar - mohu potvrdit tvrzení týpka z Ubisoftu, na konzolích se jede pouze na minimum volné paměti. Mnoho z nich upředností i další varianty typu "tiny-stl".
Nový standard pravděpodobně ponechá klasické předání hodnotou jako kopii celého objektu (tedy alespoň bude-li se držet toho, že je schopen zkompilovat i C), předání referencí či ukazatelem je (a pravděpodobně i bude) stále nejvyužívanější.
#nou - nepoužívání STL je zase s novým standardem jak-kde a jak-na-co. Třeba jejich podpora pro vlákna je dost ubohá u většiny kompilátorů (vše není ještě hotovo, apod.). Příkladem budiž std::thread::hardware_concurrency() - která má vracet počet dostupných hw vláken. Na drtivé většině implementací C++11 vrátí 0 ... super, co?
Jedinou možností pro použití je dnes pravděpodobně boost (kde boost::thread::hardware_concurrency() funguje tak, jak má), nebo si funkce prostě dopsat.
#nou & mar - Kopírovací konstruktor může být inline (resp. jelikož je rozhodnutí na kompilátorů, tak je lepší ho "forcenout" pomocí __forceinline/__attribute__((always_inline))/etc. (compiler specific)), pak je výsledný kód větší.
#OndraSej - Srovnej toto - http://pastebin.com/dKADeYes a http://pastebin.com/BGJ6EgZw, kdy v druhém případě AssertExit funkce mi vše logne (s dalšími detaily), a sama program ukončí.
Samozřejmě někde můžeš vyjímku ošetřit tak že program pokračuje dále, tam taková konstrukce jistý význam může mít - nicméně já jsem úmyslně pro toto jsem vzal příklad z wiki, který vysvětluje jak vyjímky fungují (a většina těch, kteří toto učí použijou stejný příklad) - kde taková konstrukce je useless garbage.
EDIT - tedy v zmíněném AssertExit dle typu vyjímky také provedu její ošetření uvnitř programu. Konstrukcí je také uvnitř "hezčí" než try-catch-finally blok, jelikož se jedná o switch. Co se výkonu týče, můžu přes makro volání odstranit (do release verze). _________________ 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: 16. červen 2013, 14:36:47 Předmět: |
|
|
Vilem Otte> Ne, pořád to jsou jabka s hruškama. Pokud cílem toho assertu je zabít celý program, tak try/catch bloky potřebuješ jenom na top-level (takže jeden na celý program). V kódu ti zbyde jenom to if (...) throw someException. A to klidně můžeš obalit makrem a místo if a throw psát ASSERT_THAT(....), které to zformátuje a přidá název souboru a číslo řádku. Narozdíl od té funkce ale tu výjimku můžeš zpracovat, pokud budeš chtít.
Jinak switch je pěkný, jen dokud se celý vejde na obrazovku (notebooku za 15k), pak už to je dost nepřehledné.
Lemik> ad kompilatory pro konzole - nic o tom nevím, ale celkem bych se vsadil, že pro XBoxy je dostupný MS C++ (resp. něco do Visual Studia) a ostatní mají buď GCC nebo LLVM. _________________ http://trionteam.net |
|
Návrat nahoru |
|
 |
quas4
Založen: 18. 10. 2007 Příspěvky: 199
|
Zaslal: 16. červen 2013, 15:55:26 Předmět: |
|
|
nou napsal: |
nepouzivanie STL je skor relikt minulosti. |
tak to urcite ne. STL je podle me neprehledna hruza. Ve hre kterou ted pisu (STL vubec nepouzivam) mam napriklad napsanou vlastni Map (hashed, s open addressing a linear probing) ktera je rychlejsi (insert i lookup) nez unordered_map. A navic jeji kod je i vyrazne jednodussi a prehlednejsi. |
|
Návrat nahoru |
|
 |
TeaTime
Založen: 17. 06. 2011 Příspěvky: 264
|
Zaslal: 16. červen 2013, 17:10:57 Předmět: |
|
|
quas4 napsal: |
nou napsal: |
nepouzivanie STL je skor relikt minulosti. |
tak to urcite ne. STL je podle me neprehledna hruza. Ve hre kterou ted pisu (STL vubec nepouzivam) mam napriklad napsanou vlastni Map (hashed, s open addressing a linear probing) ktera je rychlejsi (insert i lookup) nez unordered_map. A navic jeji kod je i vyrazne jednodussi a prehlednejsi. |
Já si taky občas napíšu nějaký ADT, ale rozhodně bych si nechtěl psát pořád dokola všechno sám. Když zrovna někde potřebuji zásobník a nechce se mi ho hned psát, tak si myslím, že STL nebo boost skvěle plní svou funkci.
Ohledně té rychlosti: je možné, že když si napíšeš datovou strukturu přesně podle svých potřeb, tak dosáhneš vyšší rychlosti než dosáhne obecně navržené STL. Ale celkově jsem měl za to, že ADT v STL je hodně dobře optimalizované.
Ta údajná 'pomalost' unordered_map může být způsobená taky tím, že je to poměrně nový kus kódu. Testování její rychlosti se nedá generalizovat na celé STL. |
|
Návrat nahoru |
|
 |
|