środa, grudnia 24, 2014

Tnę i przerabiam na mniejsze, czyli nieprzewidziane skutki refactoringu

Od dłuższego czasu chciałem się przyjrzeć kodowi mojego narzędzia do liczenia podobnych postów na blogu.
Biedactwo coraz gorzej sobie radziło na Raspberry Pi. Nie chodziło nawet o to, że potrzebowało ponad 2 godzin na działanie, ale jeszcze przy 128 MB sterty zwykle kończyło swoje działanie wyrzuceniem OutOfMemoryError, a niestety moje Rasbperry Pi ma tylko 256 MB i Java się rzuca przy przydzieleniu jej więcej niż 128 MB.

Usiadłem więc z IntelliJ i zacząłem zmieniać.

Najpierw chciałem zrobić to testowalne, stąd zacząłem ciąć i przerabiać na mniejsze ;-)
Podzieliłem główny kawałek narzędzia na 3 główne klasy, jedną która pobiera posty z Bloggera, drugą która je wrzuca i trzecią, która analizuje i wylicza podobne posty.

Napisałem testy do środkowej części, wyrzuciłem jeszcze na zewnątrz klasę, która buduje listy słów z postów (do niej testy miałem już od dość dawna), oraz praktycznie wszystkie klasy wewnętrzne (które nie były anonimowe).

Korzystając z testów zacząłem robić pierwsze zmiany w analizatorze i zmieniłem np. klasę Pair w taki sposób, że zamiast trzymania referencji do 2 obiektów trzymała ich indeksy w liście która i tak miałem.
Wcześniej w trakcie cięcia i krojenia powyrzucałem niektóre zmienne, a inne zacząłem serializować.

Program nadal wymagał 144 MB by działać, do tego dostrzegłem, że to co sprawia że program na PC działa szybciej, czyli wprowadzenie wielowątkowego przetwarzania sprawia największy problem.
Ponieważ trzeba przetworzyć O(N2) par to samych obiektów Pair mam ponad 2 mln sztuk, a trzymając po 2 referencje, albo 2 inty zajmują grubo ponad 50 MB RAM.

To była moja szansa ;-) zmieniłem int'y na char i voilà ;-) wszystkie obiekty Pair zamiast zajmować ponad 50 MB zaczęły zajmować 30 MB ;-)
Jest to brudny hack, ale działa ;-)

Mógłbym jeszcze Pair wyrzucić w ogóle, w końcu Rasbperry Pi ma 1 CPU, to po co przetwarzać problem wielowątkowo? Ale z drugiej strony dzięki wielowątkowości na PC cała analiza zajmuje 6 sekund.
Pair więc zostało.

Program był już w stanie działać na 128 MB, a nawet mniej, chociaż GC strasznie musiało mieszać.

Wrzuciłem programik na RPi by sprawdzić ile dłużej będzie działać...

I tu spotkała mnie niespodzianka ;-) okazało się, że to na co program wcześniej tracił około 120 minut, zaczęło się wykonywać w ~35 minut ;-)

Teraz tnę i przerabiam na mniejsze klasy w Bloggeroidzie ;-) tam z testami jednak będzie pewnie trudniej, ale i tak spróbuję.

Jak tak dalej pójdzie to jeszcze mój analizator postów z bloga zmavenizuję ;-)


Podobne postybeta
Dodajmy 3 klasy do SDK Java'y ;-)
Czy EULA (End-user license agreement) jest potrzebna w aplikacji mobilnej, czy nie?
Zrównoleglamy ;-)
Refleksje i serializacja w Java'ie - podstawy i obalanie mitów ;-)
Referencje w Java'ie