Tento článek se zabývá otázkou zda a kdy optimalizovat javovský kód. Podnětem pro jeho napsání byla diskuze v javovské konferenci na java.cz a podobně zaměřený, avšak obsahově odlišný, článek na serveru interval.cz.

Nejprve trochu historie: v začátcích byla Java často kritizována za to, že je pomalá. Rychlost Javy se tenkrát dala těžko srovnávat např. s jazykem C a proto si v této době spousta lidí kladlo otázku "jak v Javě psát efektivní (rychlé) programy". Následně se objevila spousta triků, které měly zaručit rychlejší provádění. Např. používání StringBuffer či StringBuilder pro sčítání řetězců místo operátoru + (v omezené míře platí i dnes) či procházení kolekce ArrayList pomocí metody get místo iterátorem (platí stále). Tyto optimalizace si bohužel někteří programátoři vyložili jako návody pro psaní programů a autoři "neefektivních" konstrukcí byli mnohdy pranýřováni. Jde však o nepochopení či neznalost základních pravidel optimalizace:

Ve věci optimalizace se držíme dvou pravidel:
Pravidlo 1. Nedělejte ji.
Pravidlo 2 (pouze pro experty). Zatím - tj. dokud nebudete mít čisté a neoptimalizované řešení - ji nedělejte.
[M. A. Jackson: "We follow two rules in the matter of optimizations:
Rule 1. Don't do it.
Rule 2 (for experts only). Don't do it yet - that is, not until you have a perfectly clear and unoptimized solution."]

Tento citát je z roku 1975 a více než tři desetiletí mu na platnosti nic neubraly. Další často uváděný citát týkající se optimalizace je dokonce o rok starší:

Zhruba v 97% případů bychom měli zapomenout na malé výkonnostní optimalizace: předčasná optimalizace je původem všeho zla.
[D. E. Knuth: "We should forget about small efficiencies, say about 97% of the time: premature optimization is the root of all evil."]

Proč je předčasná optimalizace špatná? Jen málokdy vede k požadovanému výsledku, protože programátor většinou nedokáže odhadnout, kde program tráví nejvíce času. Zato podstatně snižuje srozumitelnost kódu, protože ten je zaplevelen "efektivními" konstrukcemi, nad kterými si čtenář často láme hlavu. Proto by měl každý vedoucí projektu všechny "optimalizátory" vytahat za uši. Prioritou softwarového inženýra by měl být srozumitelný a čistý kód ("čistý" zde znamená bez optimalizací). Vždy je lepší nechat optimalizaci na JITu, který je napsán tak, aby uměl optimalizovat běžný ("hloupý") kód [B. Goetz: "Write dumb code."]. Neznamená to ovšem, že máme psát jako dřevorubci. Např. zbytečné volání metody je samozřejmě špatné a měli bychom se ho vyvarovat. Hranice mezi předčasnou optimalizací a kódem dřevorubce není ostrá a její vymezení může být subjektivní. Např. zápis

 

for (int i = 0, n = p.size(); i < n; i++) {
...
}

lze považovat za předčasnou optimalizaci i za elegantní vyjádření toho, že se počet prvků kolekce p v cyklu nemění.

Kdy je tedy vhodné optimalizovat? Pokud máte funkční řešení a chcete jej optimalizovat, použijte profiler a hledejte místo, kde program tráví nejvíce času [K. Pepperdine: "Measure, don't guess."]. Vždy změřte výkon před optimalizací a po ní a optimalizaci ponechte pouze pokud se osvědčí. Optimalizace, která program nezrychlí, nemá v kódu co pohledávat.

Na závěr ještě pár rad pro všechny softwarové inženýry:

  1. Zaměřte se na architekturu a návrh. Dobrá architektura je pro výkon programu zdaleka nejdůležitější.
  2. Používejte osvědčené frameworky. Frameworky jsou obvykle napsány experty v daném oboru a měly by být prosty výkonnostních neefektivností.
  3. Používejte efektivní algoritmy. Algoritmus s lepší časovou složitostí ovšem nemusí ve vašem případě dávat výsledky rychleji než jiný se složitostí horší.
  4. Pište srozumitelný kód. Z kódu by mělo být zřejmé, co jste chtěli vyjádřit.