• Nie Znaleziono Wyników

Rozdział 4. Architektura

4.1 Dobór architektury

4.1.9 Testy

Testy przeprowadzono na komputerze z procesorem Intel Pentium M 715 / 1.5 GHz i pamięcią RAM 1G. Celem eksperymentów było zbadanie wpływu synchronizacji na wydajność przetwarzania zapytań. Do badań użyto mikro-test zilustrowany na rys. 4.13. Składał się on z operatora filtracji O4, który realizował funkcję: value1 < 50. Rozmiar okien liczebnościowych wynosił 500 elementów, a predykatem operatora łącznia O5 była nierówność: value1 < value2. Taka konfiguracja skutkowała tworzeniem się na wyjściu operatora O5 dużych zgrupowań krotek w losowych momentach, co stanowiło dodatkowe obciążenie testu.

Pojedynczy eksperyment polegał na pomiarze średniego czasu odpowiedzi krotek wynikowych przy ustalonej szybkości źródeł gen1 i gen2, oraz dla zadanej konfiguracji schedulera i realizacji warstwy zasilania. Źródła danych generowały po 1000 krotek, tworząc przy tym stałe obciążenie z zakresu od 1000 do 30000 krotek na minutę. Każde ze źródeł generowało krotki z wartościami odpowiadającymi zmiennej losowej o rozkładzie równomiernym z zakresu 0-100. Konfiguracja schedulerów obejmowała algorytmy: Chain-flush oraz Round-Robin. Wpierw przeprowadzono eksperymenty dla architektury podstawowej opisanej w sekcji 4.1.2 dla schedulera Round-Robin oraz Chain-flush. Następnie zmierzono czasy odpowiedzi dla architektury zorientowanej na szybki przepływ krotek dla schedulera Chain-flush. Wymienione testy zostały przeprowadzone zarówno, gdy tworzenie operatorów złożonych było załączone (rys. 4.13 b)) jak i wyłączone (rys. 4.13 a)). Dla czytelności opis zbadanych konfiguracji zestawiono w tab. 4.1. Kolumna typ strumienia informuje czy w teście zastosowano implementację strumieni opartą na instrukcjach CAS, którą oznaczono nazwą new, albo skorzystano z standardowego mechanizmu synchronized(std).

µ ωcount σ ωcount gen1 gen2 out O0 O1 O4 O5 O2 O3 O6 O7 µ ωcount σ ωcount gen1 gen2 out O0 O1 O4 O5 O2 O3 O6 O7 a) b) G1 G2 G4 G

Rys. 4.13. Optymalizacja pamięciowa uzyskana dzięki połączeniu operatorów

Tabela 4.1. Konfiguracja eksperymentów dla rys. 4.14

Nazwa wykresu

Typ shedulera Grupowanie operatorów

Typ strumieni Typ architektury

FC3 Chain-Flush Nie new Pula wątków

FC4 Chain-Flush Nie std Pula wątków

RR2 Round-Robin Nie new Pula wątków

RR3 Round-Robin Nie std Pula wątków

FC2Loc Chain-Flush Tak new Workery

Rys. 4.14. Zestawienie opóźnień dla przeprowadzonych badań

Analiza zebranych pomiarów wskazuje jednoznacznie przewagę architektury workerów nad rozwiązaniem opartym o pojedynczą pule wątków. Jeżeli porównamy czasy odpowiedzi zgromadzone dla najwydajniejszej konfiguracji RR2 dla rozwiązania z pulą wątków, z najsłabszą konfiguracją FC2Loc opartą na nowej architekturze, poprawa jest ponad pięciokrotna dla intensywności 20000 krotek na minutę, co widzimy na rysunkach 4.14 i 4.15. Warto zaznaczyć, że zastosowanie kolejki wątków zmusza do dodatkowej synchronizacji modułów strumieniowej bazy danych, w konsekwencji implementacja bardziej złożonych schedulerów staje się mało wydajna, ilustruje to zestawienie pomiarów FC3 z RR2 i FC4 z RR3. Drugim wnioskiem wypływającym z analizy pomiarów jest trzykrotna poprawa wydajności dzięki zastosowaniu instrukcji typu CAS. Tą poprawę można odnotować porównując ze sobą wykresy FC3 z FC4 oraz RR2 z RR3. Rząd zmian pokazuje jak ważną rolę w całkowitym czasie odpowiedzi odgrywa wybór metody zasilania operatorów. Podsumowując, połączenie obu technik zaowocowało architekturą, która pozwala na wydajną obsługę złożonych algorytmów. Przykładowo dla schedulera Chain-flush zmiana architektury zaowocowała spadkiem czasów odpowiedzi z 950ms do 12ms dla natężenia strumieni wejściowych na poziomie 15000 krotek na min.

Zebrane wyniki pozwalają także odnotować dwa zjawiska. Zaskakujące jest, że analiza opóźnień architektury opartej o pulę wątków wskazuje na przewagę prostego algorytmu Round-Robin nad algorytmem Chain-fulsh. Sytuacja ta ma

0 200 400 600 800 1000 1200 1400 1600 4000 9000 14000 19000 24000 29000 L a te n c ja [ m s]

Intensywność strumieni wejściowych [krotka/min]

FC4 FC3Loc RR3 FC3 FC2Loc RR2

miejsce, ponieważ uruchomione zapytanie jest na tyle proste, że ważną rolę odgrywa czas obsługi algorytmu schedulera. Algorytm Round-Robin korzysta z prostej kolejki, podczas gdy w Chain-flush istnieją dwie kolejki priorytetowe. Dlatego z wykresów można odczytać przewagę Round-Robin. Warto też dokładniej przyjrzeć się porównaniu konfiguracji FC2Loc oraz FC3Loc na rys. 4.15. Jak widzimy sieć przetwarzania, w której załączono grupowanie operatorów (wykres FC2Loc) jest wolniejsza niż sieć przetwarzania składająca się z prostych operatorów fizycznych. Przyczyna takiej sytuacji leży w szczegółach implementacyjnych buforów strumieniowych. Strumienie synchronizowane występują tam, gdzie operator O jest zasilany, przez co najmniej jedno źródło nie należące do Wolkera, do którego jest przypisany O. Konfiguracja z załączonym grupowaniem operatorów jest zilustrowana na rys. 4.13 b). Zgodnie z definicją, połączenia synchronizowane występują pomiędzy O1-G3, O0-G4 i G2-G3. Należy dodatkowo zwrócić uwagę, że warstwa zasilająca G3

składa się z kilku buforów strumieniowych z powodu czego jest wolniejsza od warstwy zasilania składającej się z pojedynczego bufora. Konfiguracja z wyłączonym grupowaniem operatorów jest zilustrowana na rys. 4.13 a). Dla tej sieci przetwarzania strumienie synchronizowane to tylko O0-O2 i O1-O3, przy czym oba połączenia są zrealizowane przez warstwę zasilania z pojedynczym buforem. W rezultacie, pomimo że zastosowanie operacji grupowania operatorów fizycznych pozwala zredukować liczbę strumieni, bilans finalny okazał się gorszy.

Rys. 4.15. Zestawienie opóźnień dla przeprowadzonych badań

0 5 10 15 20 25 4000 9000 14000 19000 24000 29000 L a te n cj a [ m s ]

Intensywność strumieni wejściowych [krotka/min]

FC3Loc FC2Loc

4.1.10 Wnioski i uwagi

Często przyjmuje się uproszczenie w którym marginalizuje się wpływ synchronizacji operatorów w trakcie pracy schedulerów [9,10,53]. W [18] autorzy zidentyfikowali sposoby przekazywania krotek pomiędzy operatorami w ramach pojedynczego i wielu wątków, rozwiązanie to jednak poruszało tylko kwestię implementacji operatorów z pominięciem zagadnień związanych z integracją modułów strumieniowej bazy danych. Warstwa integrująca łączy wiele modułów, wprowadza dodatkowe ograniczenia, których uwzględnienie jest ważne podczas optymalizacji. Ta luka wiedzy o strumieniowych bazach danych zainspirowała do badań nad wielowątkową implementacją przetwarzania strumieniowego oraz oceną szeroko rozumianej synchronizacji na czasy odpowiedzi. Należy zauważyć, że zaproponowane rozwiązania korzystają z ogólnodostępnych mechanizmów programowania współbieżnego, co pozwala je zastosować nie tylko w środowisku Java.

Analiza komunikacji operator-operator i operator-scheduler wskazała, że obecne algorytmy schedulerów szeroko pomijają ograniczenia związane z implementacją wielowątkową i rozproszoną. Aby wydajność operatorów strumieniowych nie została stłumiona przez warstwę zasilającą. W tym podrozdziale zwrócono uwagę na dysproporcję pomiędzy intensywnością komunikacji pomiędzy modułami strumieniowych baz danych, a częstością wymiany krotek pomiędzy operatorami. Uwzględnienie tego czynnika było podstawą nowej architektury modułu workerów.

Przeprowadzone testy pokazały, że nowa architektura znacząco obniża czasy odpowiedzi. Wprowadzone rozwiązanie cechuje się tym, że nie tylko wydajnie koordynuje pracę pomiędzy operatorami i schedulerem, ale również umożliwia dołączanie innych funkcjonalności do workera bez konieczności dodatkowej synchronizacji. Przeprowadzone badania objęły również studium wyboru algorytmów realizujących wymianę komunikatów i krotek pomiędzy workerami. Finalnie zaadaptowano algorytmy klasy non-blocking and wait free, które korzystają z instrukcji typu CAS oraz własności modelu pamięci JVM. Ta grupa instrukcji pozwoliła zmniejszyć trzykrotnie czasy opóźnień krotek wynikowych. Ponadto zaproponowane rozwiązanie jest uniwersalne, ponieważ specyfikacja modelu

pamięci JVM ogranicza się do technologii ogólnie dostępnych w systemach komputerowych.

Przeprowadzono dodatkowo testy algorytmu grupowania operatorów. Okazało się, że nie możliwa jest analiza zebranych wyników bez uwzględnienia ograniczeń warstwy zasilania, ponieważ wpływ synchronizacji na czasy odpowiedzi jest wysoki. W rozważanym przypadku ograniczenia warstwy zasilania sprawiły, że można było zmniejszyć dwukrotnie obciążenie pamięciowe dla operatora okna liczebnościowego i operatora łączenia albo skrócić o około 20% czasy odpowiedzi. Przyczyną takiego efektu jest budowa warstwy zasilania, która wymaga synchronizacji wszystkich strumieni wejściowych w chwili, kiedy co najmniej jedno ze źródeł operatora O nie należy do workera, w którym jest zarejestrowany ten operator.

Zebrane wyniki podczas testów architektury strumieniowej bazy danych stały się przyczynkiem do przeprowadzenia oddzielnych badań nad optymaliza-torami grupowania oraz modelem estymującym czasy odpowiedzi, co zostanie przedstawione odpowiednio w podrozdziałach 4.3 i 4.2.