Černá magie testů výkonnosti

Většina vývojářů věří, že je dobrá v ladění výkonu, ale obecně se ukazuje, že většina vývojářů v tom dobrá není.
Kirk Pepperdine

Tento citát z rozhovoru s Kirkem Pepperdinem jsem tu použil záměrně. Chci tu psát o svých nedávných zkušenostech s měřením a laděním výkonu, ale vzhledem k tomu, že jsem docela dobrý vývojář, je velká pravděpodobnost, že jsem na to šel špatně.

Takže jste byli varováni a já se může pustit do popisu problému. Pracuji na jednom velkém a zbytečně složitém systému. Nedávno se po jedné podařené marketingové akci velká skupina zákazníku rozhodla, že ho začne volat v jeden okamžik najednou. Navíc ještě k tomu v pátek večer. No a protože to je docela velká skupina, náš systém s tím měl drobné potíže. Kolegové s řešením strávili pěkných pár dnů, nakonec našli místa potencionálních problémů a před systém postavili pár obraných mechanizmů, které ho chrání před přetížením. Nicméně problém stále trvá a bylo by pěkné ho vyřešit. Jinak by se mohlo stát, že se z velké skupiny stane malá, což by mohlo potěšit naše administrátory, ale rozhodně ne náš marketing.

Teď přicházím do hry já. Kolegové mi ukázali na jednu věc, kterou aplikace dělá evidentně zbytečně a ať prý vymyslím, jak se jí zbavit, aniž by se něco rozbilo. Jenže já jsem známý potížista a navíc jsem si vzpomněl na jednu přednášku Kirka Pepperdineho, v které říkal něco v tomto smyslu (nedaří se mi najít zdroj, takže cituji z paměti):

  1. Nejdřív si zjistěte jaký je požadovaný výkon (SLA)
  2. Naměřte současné hodnoty
  3. Zjistěte možné problémy
  4. Jeden z nich opravte
  5. Naměřte nové hodnoty
  6. Opakujte dokud nesplníte 1. nebo dokud má zákazník ještě nějaké peníze

Takže jsem si zjistil SLA a začal měřit. A už tady jsem možná udělal chybu. Začal jsem měřit na svém notebooku a ne na prostředí, které se podobá produkci. Mojí výmluvou je to, že jsem si myslel, že už víme v čem je problém. A opravdu, při testech se projevovala potíž v té jedné nadbytečné operaci. Zbytečně se tam zapisovala data do jedné tabulky. Z té se obratem zase četlo a občas tu jeden select zabíral desítky sekund. Cože? Desítky sekund u dotazu nad tabulkou v které je jen pár set tisíc záznamů? Něco je špatně. Po chvíli pátrání jsem objevil, že někteří klienti mají v dané tabulce stovky záznamů místo očekávaného tuctu a pro ně trvá dotaz neúnosně dlouho. Jeden dobře mířený index nad tabulkou, která na daný dotaz zdánlivě neměla vliv to vyřešil.

Tento problém moji pozornost obrátil na test samotný. Jak je možné, že data vypadají jinak, než je očekáváno? Ukázalo se, že chyby mohou být i v testu samotném. Místo simulace tisíců různých klientů, simuloval tisíce přístupů od pár desítek klientů. Takže den testování v čudu, ale jsme alespoň o krok blíž. Máme opravený test.

Spustím opravené testy a aplikace je stále podezřele pomalá. Navíc i když spouštím JMeter, aplikaci i databázi na jednom stroji, zátěž procesoru dosahuje ubohých 75%. Brzdou je něco jiného. Vypadá to, že disk. A opravdu MySql proces zapisuje a čte jak divoký. Že by to přece jen byly ty zbytečné inzerty. To se zjistí velice snadno, prostě je vyhodím.

Po pár minutách hledání nejlepšího místa pro sabotáž, vyřazení inzertů z boje a desítkách minut buildu a startu serveru nedočkavě spouštím test a ... chvilka napětí ... jste tak napjatí jako já ? ... vážně ? ... výsledky jsou srovnatelné s předchozími. Obě jádra se pořád flákají, disk maká jak afroameričan.

Takže dalších pár hodinek pátrání a nacházím tabulku, která na první pohled s testem moc nesouvisí. Ale předchozí testy do ní nasypaly hromadu dat, která teď zdržují. Vymažu obsah tabulky, znovu spustím test a graf výkonu málem proletěl vrškem monitoru. Požadovaný výkon bych možná splnil i na notebooku!

Problém vyřešen. Nebo ne? Co se stane, když inzerty vrátím? Další desítky minut strávené novým buildem a spouštím test. Sakra, je to srovnatelně rychlé, jako když tam ty inzerty nejsou.

Ukazuje se, že obsah databáze a způsob testování má na výkon větší vliv, než struktura kódu! To je trochu nečekaný výsledek. Jediné co jsem udělal bylo, že jsem opravil test, přidal jeden index a promazal tabulky. A už to mělo za následek dvojnásobné zvýšení výkonu. Alespoň toho naměřeného. Takže jsem tam kde jsem začal. O tom kde nás tlačí bota nevím skoro nic. Že by měl Kirk pravdu? Že by programátoři byli opravdu špatnými testery? Tomu se mi nechce věřit. Nevzdávám to a zítra se vrhnu na testy v reálném prostředí. To by v tom byl čert, abych na něco nepřišel.

4 Responses to “Černá magie testů výkonnosti”

  1. R Says:

    Jedna z veci, kterou nam tloukli do hlavy na elektru byla opakovatelnost experimentu. Unit testy jsou toho krasnym prikladem. Bohuzel ale vidim trend (v nasi spolecnosti roky zakoreneny proces), kdy ma release 6 tydnu testovaci fazi, kdy je kod postupne nasazovan na diametralne odlisna prostredi a testovan z leva z prava(obcas taky vubec ne, jak se ukazalo nedavno), ale o vypovidaci hodnote takovych testu se prilis neuvazuje. Efektivita vynalozenych prostredku jde ruku v ruce s tim. Cili mene prostredi je dobra vec. Pochopitelne se malokdy clovek dostane na takovou uroven izolace testu, aby si jej pustil na produkci a nic nerozboril, v zatezovem testovani tim spis, ale mit 6 ruznych prostredi...?

  2. lzap Says:

    Zapomenuty index neni magie 😉

  3. Lukáš Křečan Says:

    Já jsem to tam napsal, ale málo zdůraznil. Ten index se projevoval jenom při špatném testu. Při normálním provozu by neměl mít zásadní vliv.

  4. wojtha Says:

    Testování výkonnosti DB, pokud se bavíme o milionech řádků a GB dat je vždycky magie - do hry vstupuje HW a celková konfigurace serveru. Bez toho aby se to testovalo na ekvivalentní konfiguraci jako bude mít produkční server nemá IMHO vůbec smysl.

    Viz např.

    MySQL 5.1 partitions in practice
    http://dev.mysql.com/tech-resources/articles/testing-partitions-large-db.html

    Citace:
    ---------
    Testing partitions has been a tiring experience. Gaining performance improvements is not a straightforward operation. What I assumed was a painless change turned out to be a long trial-and-error process.
    There is no silver bullet

    Applying a partition change to a table is no guarantee for performance improvement. The gain depends on several factors:

    * the column used for partitioning;
    * the function used for partitioning, where the native column type is not an integer;
    * the server speed;
    * the amount of RAM.

    Nothing should be taken for granted.
    ---------

    Důležitá je izolace změn a důkladné měření (alespoň 4-5 měření u každého testu). U Mysql je také důležité při více stejných měření vypnout query cache (select SQL_NO_CACHE).