Wydajność aplikacji

Autor: Grzegorz Mańturzyk

Jakiś czas temu podczas wizyty u jednego z naszych Klientów rozmawialiśmy o tym, jak sprawnie działa sieć, aplikacje, serwery i tego typu sprawy. Przy okazji klient przyznał, że jest jedna kwestia, która go martwi, a mianowicie bardzo wolna transmisja plików przez łącze WAN.

Otóż klient posiada łącze międzymiastowe o przepływności 1 Gbit/s. Kiedy próbuje przesłać duży plik, np. obraz płyty DVD, trwa to prawie 15 minut, gdy tymczasem prosty rachunek wykazuje, że powinno to trwać niecałą minutę.
Klient sprawdził co się tylko dało. Dyski, pamięć i procesory na serwerze plików i stacjach użytkowników. Wszystko było OK. Więc przyczyna leży po stronie operatora, który dostarcza łącze. Ale operator mówił, że u niego wszystko też było wszystko w porządku.


Postanowiliśmy sprawdzić jak to jest z przepływnością tego łącza. Podłączyliśmy urządzenia pomiarowe na obu końcach i okazało się, że przepływność wynosi… pełne 1 Gbit/s. Bez strat. Opóźnienie wprowadzane przez łącze było minimalne jak na odległość, zaledwie 10 milisekund. Wyglądało na to, że chcąc nie chcąc, trzeba zamknąć otwarte u operatora zgłoszenie problemu i pogodzić się z losem.
Ale nie poddaliśmy się tak łatwo. Postanowiliśmy przyjrzeć się dokładniej ruchowi na tym łączu, jaki był generowany podczas transmisji pliku. Zarejestrowaliśmy za pomocą analizatora sieciowego kawałek ruchu. Okazało się, że dane są przesyłane w dość małych porcjach po 64 kB. Co to oznacza? Serwer plików po wysłaniu 64 kB danych czeka na potwierdzenie ze stacji roboczej – tak, jak to się normalnie odbywa w protokole TCP. Z powodu opóźnienia na łączu przesłanie porcji 64 kB danych zajmuje 10 ms. Kiedy plik jest duży, jednostkowe czasy kumulują się i faktycznie, wychodzi kilkanaście minut…
Trzeba było coś z tym zrobić. Najlepiej zmusić serwer do przesyłania danych w większych porcjach. Jeżeli porcje będą większe, to do przesłania całego pliku będzie ich potrzeba mniej. Na przesłanie każdego z nich też będzie potrzeba dziesięciu milisekund, ale że porcji będzie mniej, więc sumaryczny czas przesłania całego pliku będzie dzięki temu krótszy.


Eksperymentowaliśmy cały dzień z różnymi opcjami konfiguracyjnymi. I nic. Nawet wszechwiedzący Google nie pomógł. No cóż, widocznie Windows, a konkretnie protokół CIFS tak ma.
Aż wreszcie doszukaliśmy się informacji, że za wielkość pakietów odpowiada nie tylko protokół CIFS, ale również leżący „pod nim” protokół TCP, a konkretnie parametr zwany Advertized Window Size. Jeżeli wielkość tego okna jest mała, to pakiety też są małe. Standardowo w systemie Windows Server okno jest ustawione na 64 kB.
Olśnienie! Ależ tak, tu leży pies pogrzebany! Trzeba w systemie operacyjnym serwera powiększyć okno i problem będzie rozwiązany! Optymalna wielkość okna to iloczyn przepływności łącza i opóźnienia, a więc w naszym przypadku ponad 1 GB. Subtelna różnica w porównaniu z 64 kB, nieprawdaż?
Powiększyliśmy okno TCP, zrestartowaliśmy serwer, pełni optymizmu rozpoczęliśmy transmisję pliku i… porażka. Transfer wciąż był bardzo powolny, a porcje danych jak wcześniej, tak i teraz miały po 64 kB. Albo ten protokół CIFS rzeczywiście tak ma, albo z tym oknem TCP to lipa jakaś…

Jeszcze jedna próba, tym razem z protokołem FTP zamiast CIFS. To samo. Żadnej różnicy. Transfer bardzo powolny, a porcje danych mają wciąż po 64 kB.
Jako jedyne rozwiązanie jawił się więc zakup akceleratorów sieciowych. Za jedyne kilkaset tysięcy złotych transmisja jest przyspieszana kilkudziesięciokrotnie, jak to z entuzjazmem mówił dostawca. Klient powoli zaczął przyjmować do wiadomości konieczność tego wydatku…
Ale nie poddaliśmy się tak łatwo. Po kolejnych dwóch dniach buszowania w Google znalazłem informację, że za wielkość porcji danych odpowiada nie tylko okno protokołu TCP, ale również tajemniczo brzmiący „socket”. Co to jest ten socket? Otóż w dużym uproszczeniu, jest to bufor wykorzystywany przez aplikację podczas transmisji plików. Jak duży socket, tak duża porcja danych. Jeżeli socket i okno TCP są różnej wielkości, to dla porcji danych wybierana jest mniejsza wartość.

Powiększmy więc socket! Gdzie się powiększa socket w protokole CIFS? Telefon do Microsoftu! Odpowiedź specjalisty brzmiała: faktycznie, jest coś takiego jak socket, ale nie da się go powiększyć. Jest na stałe ustalony. Zarówno dla protokołu CIFS, jak i FTP. No tak…
Znowu Google, tym razem ze słowami: server FTP configure socket. Jest coś! Jest aplikacja serwera FTP z konfigurowalnym socketem!
Wyłączyliśmy standardowy protokół FTP w Windows uruchomiliśmy nowy serwer z odpowiednio dużym socketem i oknem TCP. I obraz płyty DVD przefrunął z jednego końca Polski na drugi w ciągu niecałych dwóch minut. Prawie dziesięć razy szybciej, niż pierwotnie. Teoretycznie powinno to trwać jeszcze krócej, mniej niż minutę, ale nie czepiajmy się szczegółów…
Administrator był zadowolony. Rozwiązał problem. Jego prestiż u prezesa wzrósł. Prezes był zadowolony. Zamiast akceleratorów sieciowych kupił sobie nowe Audi. A przede wszystkim zadowoleni byliśmy my, bo najważniejszy dla nas jest zadowolony klient!
Niedawno zadzwonił do mnie ten sam klient z pytaniem o pomoc w sprawie jednej z aplikacji opartej o Oracle, która po przeniesieniu serwerowni zaczęła nieznośnie wolno działać. Oczywiście niezwłocznie podążyłem z pomocą, ale o tym w następnym odcinku…