Wydajność i wielkość obiektów interfejsu programów napisanych w Java (SWT)
We wstępie opiszę krótko potrzeby pisanych przeze mnie dwu programów, które poprowadziły mnie do rozwiązań zastosowanych w projektach. Podobieństwo tych aplikacji do siebie nie jest przypadkowe, a rozwiązania które stosuję powstały w moim programowaniu już wcześniej.
Oto opis sytuacji pierwszej:
program pierwszy
„Rejestr eksploatacji pojazdów budowlanych”
Program powstał jako rozwiązanie dedykowane dla mojego klienta. Już w jednym z wcześniejszych tekstów zasygnalizowałem, że negocjując cenę usługi, zaproponowałem jej obniżenie w zamian za uprawnienie do sprzedaży tej aplikacji innym klientom. Oprócz kilku funkcji konfiguracyjnych oraz modułu statystyk, podstawowym zadaniem programu pozostaje na podstawie rejestrowanych danych o przebiegu, zużyciu paliwa i oleju, sygnalizowanie konieczności wykonania „okresowych przeglądów technicznych pojazdów”.
Klient uprzedził mnie o konieczności oszczędzenia czasu na czynności wprowadzania danych do rejestru (w jego słowach brzmiało to: „to ma być prosty program”, co mi natychmiast nasunęło myśl „nie mamy czasu na to żeby zajmowało nam to kilka godzin...”). Mowa była o rejestrowaniu kilkunastu dokumentów zawierających dane w rodzaju: stan licznika, ilość pobranego paliwa, ilość pobranego oleju – sprawa jest o tyle uproszczona, że mój klient posiada własny dystrybutor paliwa, magazyn na materiały eksploatacyjne (tu: olej) i rejestr nie miał rozliczać stanów tych magazynów.
Rozwiązanie sytuacji:
Podczas testów rozwiązania, które powstało w mojej głowie, z „rozpaczą” obserwowałem jak spada prędkość odświeżania danych przy zapisywaniu kolejnych nowych rekordów w bazie danych rejestru. Testy wtedy wykonywałem dla zaledwie siedmiu różnych „pojazdów” i gdy rejestr zawierał około 35 tygodni (dla każdego „pojazdu” jeden wpis tygodniowo) wydajność aplikacji zaczęła zauważalnie spadać.
Przyczyną spadku prędkości okazała się pętla kopiująca do obiektu „Table” (SWT) dane pobrane z bazy danych. Rozmiar danych pozostawał „do przyjęcia”, ale założone przeze mnie ograniczenie okresu danych do jednego roku wstecz, okazało się zbyt optymistyczne.
Z pomocą przyszedł przykład internetu (nie nie – nie chodzi tu o gotowy kod z rozwiązaniem), otóż strony internetowe są świetnym przykładem „segmentacji” (rozbicia na równe przedziały) danych pobranych z bazy danych. Ostatecznie okres czyli wsteczny przedział czasu zmniejszyłem do około 50 ~ 70 rekordów rejestru co z dużym „zapasem” ograniczyło wielkość zapytań oraz zabezpieczyło możliwość porównywania danych i poprawiania pomyłek nawet popełnionych w zapisach z przed 2~3 tygodni. Innym rozwiązaniem było by pełniejsze „zaczerpnięcie” z rozwiązań internetowych i dodanie przycisku „pokaż starsze zapisy”.
Opis drugiej sytuacji:
Program drugi:
„Kalendarz przeglądów maszyn produkcyjnych”
Ponownie rejestr, lecz założenia (potrzeby) klienta inne. Mój klient to firma produkcyjna, która posiada kilkadziesiąt maszyn produkcyjnych. Maszyny te według przepisów, muszą przechodzić co najmniej raz w roku „przegląd sprawności technicznej”. Klient postawił przede mną zadanie konsekwentnego planowania z interwałem rocznym takich przeglądów z możliwością rejestracji napraw (tu: wraz z kosztami napraw oraz ich zakresem). To proste zadanie realizują następujące okna programu:
„dodaj/edytuj” (obiekt – maszynę)
„przeglądy” (terminy dla maszyn)
„historia” (przeglądów obiektów – maszyn)
Mam nadzieję, że przy odrobinie wyobraźni widzicie, że wszystkie trzy okna to ten sam obiekt z przekonfigurowanymi funkcjonalnościami, których ceną dla pamięci jest (przy najmniejszym z tych okiem) zadeklarowana, lecz nie wykorzystana pamięć dla kilku nie występujących w danym kontekście kontrolek. Mimo to rozmiar całości aplikacji jest znacząco mniejszy od programów korzystających z oddzielnych obiektów dla poszczególnych (często podobnie wyglądających) okien.


