[Javalist] Segítség! Java7 compiler BUG???

istvan.ketler at lhsystems.com istvan.ketler at lhsystems.com
2012. Júl. 25., Sze, 13:33:10 CEST


Ámen.

Szeretnék annyit hozzátenni, hogy programozó ne foglalkozzék azzal, hogy mi a hatékonyabb. A programozó írjon nagyon szép, olvasható kódot, aztán tesztelje (ha lehet éles adatokkal, még jobb ha éles környezetben), végezzen méréseket, és ahol tényleg lassú, ott kezdjen optimalizálni.

Kikerestem a vonatkozó részt a kedvenc könyvemből:

"... egy program egyszerű, kézenfekvő megírásával elérjük azt, hogy helyesen működjön, és a minimumra csökkenjen a zavarosság veszélye. Ezután teljesítményméréseket végezhetünk, hogy eldöntsük, elég jól működik-e, és ha nem, mire kell a figyelmünket összpontosítani. Egy adott algoritmusnál a sebességet szinte minden esetben csak az olvashatóság rovására növelhetjük. Csak akkor áldozzuk fel az áttekinthetőséget a sebességért, ha tudjuk, hogy a helyes feladatot oldjuk meg helyesen és tudjuk, hogy ez megéri az áldozatot."

A könyvet, amiből idéztem, Kernighan írta (Plauger a szerzőtárs) 1976-ban (!), és hihetetlenül modern, mind a mai napig érvényes elveket mutat be gyakorlati példákon keresztül (külön érdekesség, hogy "Ratfor" nyelvet használ ehhez, ami a Fortran C-sített változata - csaknem olyan, mintha régi C kódot olvasnál). Csak az azóta eltelt időben objektum orientált, code reuse, test driven development, és más hasonló egzotikus állatneveket aggattunk ezekre az elvekre...

Kernighan-Plauger: Software Tools (1976)
"A programozás magasiskolája" címmel a műszaki könyvkiadó kiadta a fordítását magyarul 1982-ben. A mai napig hálás vagyok a sorsnak, hogy annak idején zöldfülű kezdőként megvettem és nagy figyelemmel kiolvastam (és feldolgoztam). Szerintem kezdőknek a mai napig érdemes használni (mint ahogy a Unixot és származékait is, amik pedig kortársai a könyvnek - csak a Unixok azóta fejlődtek, de ezek az elvek alig változtak, legfeljebb lett még néhány belőlük).

Az idő előtti optimalizálás pedig minden rossz gyökere ezen a Földön... :)

Üdvözlettel,

Iván
István Ketler
Senior Consultant
Lufthansa Systems Hungaria Kft.
Development Center Pest
Neumann János u. 1/e
1117 Budapest
Hungary
Tel: +36 1 887-2815
Fax: +36 1 887-2977
Mobile: +36 30 600-4936
Room: Infopark E, Room LH2-24
e-mail: istvan.ketler at lhsystems.com<mailto:istvan.ketler at lhsystems.com>
Internet: www.LHsystems.hu<http://www.lhsystems.hu/>

From: javalist-bounces at lists.javaforum.hu [mailto:javalist-bounces at lists.javaforum.hu] On Behalf Of Peter Verhas
Sent: Wednesday, July 25, 2012 12:23 PM
To: Java lista
Subject: Re: [Javalist] Segítség! Java7 compiler BUG???

Mesélni nem szeretek, illetve igen, de az a gyereknevelés vagy a csajozás témaköre, ez meg egy szakmai fórum, ahol a kőkemény tények számítanak. Persze szellemileg nagyon fel tud frissíteni egy olyan téma, hogy jobb-e exception-t dobni, vagy inkább null-t visszaadni egy metódusból amennyiben abból a szempontból vizsgáljuk meg, hogy melyik eredményez a hívó oldalon olvashatóbb kódot. Ez mindaddig szubjektív, amíg nem végzünk mérést sok átlagos programozón, definiált metrikával, ami méri, hogy mennyire olvasható a kód. Gyakorlatilag ez kivitelezhetetlen, ezért ilyenkor a common sense dönt; illetve az idő, ami éveket jelent. Idővel kiderül, hogy mi a jó, mi a rossz, és sok minden marad azon a mezsgyén, amire a legmegfelelőbb szó a "megfelelő".

Tipikusan például ilyen a singleton. Baromi jól el lehet vitázni, hogy a singleton pattern, vagy antipattern (talán erről is írok majd egy blogbejegyzést, meg ezekből a hosszabb levelekből is), de leginkább azt lehet mondani, hogy nem rossz. Megfelelő. Arra amire.

A tények azonban makacs dolgok, és ha mégoly szép kódot is eredményez egy programozási módszertan, ha használhatatlan  a kód, ami az alapján készül, akkor az nem egy jó pattern (ezt írtam az előző levelemben is, kedves néném...) Anno ezen halt el az Algol60 meg az Algol68 is: nem volt olyan gép, ami le tudta volna fordítani gyorsan és jól: maradt a FORTRAN a kor kódolóinak.

Az a mondás, hogy ne dobjunk Exception-t, mert az lassú überel mindent. Hiába lesz szép és olvasható a kód ha egy null-t visszaadó metódus 1000-szer gyorsabb, mint egy olyan, amelyik egy 'new Exception()' -t dob. (kb. ez az arány, beleértve a try/catch kezelést is, olyan metódusoknál, amelyek egyébként nem csinálnak semmit).

Konkrétan csak egy 'return null'-t visszaadó metódust tíz milliószor meghívva 12ms alatt végez a gépem, míg ugyanennyiszer egy olyat, ami egy Exception-t dob 23ms-ig is eltart. Hogyan?

VIGYÁZAT CSALOK!

Ha minden egyes alkalommal új Exception-t hozok létre, akkor ez az érték már 11000ms, majdnem ezerszer lassabb. De ha ugyanazt az Exception-t dobálom?

Ez azt mutatja, hogy teljesítmény szempontjából nem az a kérdés, hogy null-t adjak-e vissza, vagy kivétel dobásával jelezzem a speciális visszatérési értéket, hanem azt, hogy nem feltétlenül kell minden egyes esetben új Exception objektumot létrehozni.

Persze azt is tudni kell, hogy ilyen esetben az exception objektum stack trace része használhatatlan, hiszen nem azt fogja tartalmazni ahol akkor járt a program, amikor el lett dobva, hanem azt amikor és ahol létre lett hozva. A kérdés az, hogy kell-e nekünk a stack trace?

Ha olyan exception-t dobunk, amelyik kivételes esetet jelez, tipikusan emberi beavatkozást fog igényelni, meg kell hogy jelenjen a log-ban a stack trace, hogy lehessen tudni, hogy honnan lett dobva, akkor létre kell hozni egy új exception objektumot, tipikusan a szokásos

throw new Exception()

pattern szerint. Amikor ezt tesszük a programnak már úgyis betették a kaput, a teljesítménynek nem számít, hogy a szerver X+12ms vagy X+12mp alatt áll le (itt X az az idő ami még ezen kívül kell a leálláshoz).

Ha viszont olyan kivételt dobunk, ami nem különleges helyzet, csak jelezni akarjuk például, hogy nincs több adat, vagy nincs keresett adat, akkor (ha egyébként ez megfelel az ízlésünknek, és minden egyéb feltételnek) csak a teljesítmény szempontokat figyelembe véve dobhatunk egy private static final változóban tárolt exception-t. A metódus futási idejének csak kis része lesz (mondjuk 1%-a) a visszatérés maga, így ha ez kétszer annyi időt vesz igénybe a hívó oldalon, akkor fél százalékkal nőtt a metódus bruttó futási ideje (bruttó alatt a hívási oldali költségeket is figyelembe vesszük, try/catch/finally és társai).

Ez tehát nem támasztja alá, hogy ne dobjunk exception-t nem kivételes helyzetben. Kicsit lassabb, de elviselhető. Ezzel némileg ellentmondok az Effective Java könyvnek, de nem lehet vele vitázni, mert csak annyit ír, hogy "egy száz elemű tömbnél az én gépemen kétszer annyi ideig tart". Ez nem precíz. Hidd el neki. Vagy ne hidd el, hanem mérd meg! Én erre az utóbbira szavazok: a konkrét méréseket, meg kódot majd felrakom a blogra, és továbbra is folyhat arról a vita, hogy melyik a szebb pattern: null-t visszaadni, vagy exception-t dobni (és persze van egy harmadik pattern is, ami azt mondja, hogy legyen hasNext() kinézetű metódus).

--
Verhás Péter
peter at verhas.com<mailto:peter at verhas.com>
+36(30)9306805
skype: verhas




On 2012.07.25., at 10:50, István Székely wrote:


Sziasztok!

Péter, erről légy szíves mesélj, mert úgy érzem, lemaradtam valamiről.

A kivételkezelés Javaban is lassú (volt?). Ennek oka pontosan a stack trace összeállítása. A hívási lánc bejárása és a stack trace összeállítása igen drága művelet. Pont ebből az okból javasolja Joshua Bloch is, hogy kivételkezelést ne használjunk vezérlési szerkezetek helyett. Emiatt nem jó az sem, hogy az említett JPA metódus is kivételt dob null visszaadása helyett (persze emellett is lehet érvelni, és hajlamos is vagyok elfogadni, de az most más téma).

Ahonnan van: Effective Java, 2nd ed
Item 57: Use exceptions only for exceptional conditions

Üdv,
Stivi


On 2012-07-24 23:26, Peter Verhas wrote:

Technológiai okok miatt C++ és C# (általánosan .NET) környezetben nem szeretünk exception-t dobni (én magam programozni sem szeretek ezekben a környezetekben, nem is tudok (nagyon), hát még kivételt dobni). Ezekben a környezetekben a kivétel dobása drága, egészen más a kivételek szerkezete, és ezért nem is ad megfelelő információt. Tipikusan nincs benne a stack trace, ezért ha egy szinttel feljebb, mint ahonnan dobták nem kapjuk el, akkor már nem is lehet tudni, hogy honnan dobták. Akkor meg már olcsóbb futási időben a megfelelő hibakód visszaadása, és ennek nagy hagyománya van unix C és Windows C programozási környezetben, régen bevált. [Megjegyzés: ennek a bekezdésnek az egyik fele nem első kézből való információ, csak beszélgettem .NET-es kollégákkal. A másik fele viszont ezer évvel ezelőtti C programozási emlékek megmaradt halvány foszlányai.]

A Java egészen más. Java-ban az exception hordozza a stack trace-t (vagy nem, de inkább igen, mint nem), és ebben nagyon sok szimbolikus információ benne van. Nem kell ott elkapni, ahol dobják, vagy egy szinttel feljebb, mert minden szükséges információ benne van, és ezért elég ha ott kapjuk el, ahol kezelni tudjuk. Ezért lett egyébként kitalálva a hiba dobás, és véleményem szerint a .NET környezet az exception dobás, mint pattern funkcionalitásának egy részét feláldozta a teljesítmény oltárán, amit viszont mostanra (Java6, 7) kezd túlhaladni az idő.


_______________________________________________
Javalist mailing list
Javalist at lists.javaforum.hu<mailto:Javalist at lists.javaforum.hu>
http://lists.javaforum.hu/mailman/listinfo/javalist


 
Sitz der Gesellschaft / Corporate Headquarters: Lufthansa Systems Hungaria Kft, Budapest, Fövarosi Birosag 01-09-463417
Geschaeftsfuehrung / Management Board: Monika Houck


--------- következő rész ---------
Egy csatolt HTML állomány át lett konvertálva...
URL: <http://lists.javaforum.hu/pipermail/javalist/attachments/20120725/1e15834d/attachment.html>


További információk a(z) Javalist levelezőlistáról