RSS

32 czy 64 bity? 21

Posted by Marek Majkowski 54 days ago

Parafrazując tytuł jednego z poprzednich postów, ten powinien brzmieć “64 bitom mówimy papa”.

Nie jest żadną tajemnicą, że w Gronie używamy Linuxa. Niczym nowym też nie jest, że serwis stoi na frameworku Django. Podobno jesteśmy największym serwisem używającym tej technologii.

Jednak nie dla wszystkich jest jasne jak wygląda Django od strony serwerowej…

Podczas surfowania po Gronie, Twoje żądanie dotyczące strony grona (request) trafia do jednego z naszych serwerów. Następnie serwer przypisuje obsługę Twojego requesta jednemu z wielu procesów Django. Pojedynczy proces generuje stronę Grona, ale może obsługiwać tylko jedno żądanie na raz. Linuxowcy mogą znaleźć podobieństwo w tym modelu z modelem “prefork” z konfiguracji Apache. Po wygenerowaniu strony proces jest znów dostępny i czeka na kolejne kliknięcia użytkowników.

Wynika z tego, że na pojedynczym serwerze możemy obsłużyć na raz tylko tyle żądań, ile mamy uruchomionych procesów Django1. Niestety, pojedynczy proces zużywa dość dużo pamięci. Aby móc obsługiwać jak najwięcej użytkowników na raz, wypadałoby mieć możliwie dużo uruchomionych procesów. Jednak ich ilość jest limitowana wielkością pamięci operacyjnej.

Aby zwiększyć wydajność (czyli ilość stron które możemy wygenerować), staramy się w miarę możliwości zmniejszać wielkość pojedynczego procesu. W tym celu możemy zmniejszać ilość linii kodu lub optymalizować zużycie pamięci operacyjnej przez proces. Niestety oba zadania są bardzo trudne.

Ostatnio wpadliśmy na inny pomysł.

Nasze serwery używają 64 bitowej wersji linuxa. Administratorzy zdecydowali się na to już dawno temu. Głównym argumentem było to, że zamierzaliśmy używać większej ilości RAMu niż 4GB, oraz lepsza wydajność tej architektury.

Padł pomysł, żeby sprawdzić ile RAMu zaoszczędzimy przenosząc się na “stare” 32 bity. W sumie to w Pythonie całkiem sporo pamięci zajętej jest przez wskaźniki, a właśnie zmniejszenie jej dałoby największy zysk.

Efekt okazał się dużo lepszy niż przewidywaliśmy. W pełni załadowany proces Django na 32 bitach zajmuje około 60MB, czyli o 30% mniej niż na 64 bitach, gdzie jest to 95MB.

Oto przykład “topa” z maszyny 64 bitowej. Kolumna RES pokazuje orientacyjne zużycie pamięci przez proces:
VIRT  RES  SHR S %CPU   TIME+  COMMAND
212m  96m 3832 S    0  1:49.61 django '/gallery/3329236/0/'
203m  96m 3120 S    0  1:37.78 django '/gallery/4871149/6/0/'
211m  95m 3832 S    0  1:38.74 django '/mailbox/box/1/'
210m  95m 3824 S    0  1:45.45 django '/gallery/photo/40328359/'
210m  95m 3844 S    0  1:48.43 django '/users/index/'
210m  94m 3848 S    0  1:33.94 django '/users/'
A oto, dla porównania, analogiczny z maszyny 32 bitowej:
VIRT  RES  SHR S %CPU    TIME+  COMMAND
68396  62m 3484 S    0  2:06.94 django '/users/433317/'
67716  61m 3488 S    0  1:50.23 django '/gallery/photo/42009962/'
66264  60m 3488 S    0  2:01.94 django '/pub/join/'
65312  59m 3484 S    0  2:08.75 django '/users/'
65148  59m 3508 S    0  1:48.02 django '/users/1533943/friendlist/'
64884  59m 3508 S    0  1:51.48 django '/'

Podsumowując, możemy powiedzieć, że stosowane 64 bitów może nie być takie wspaniałe. Architektura x86_64 niewątpliwie ma wiele zalet, jednak w naszej sytuacji, gdzie ilość zajętego RAMu zaczyna mieć znaczenie, zaczynamy odczuwać jej wady.

Teoretycznie, po całkowitej migracji na 32 bity bylibyśmy w stanie obsługiwać o 1/3 więcej ruchu niż obecnie. Mamy więc o co walczyć.


1 W praktyce nie jest to takie proste, bo mamy także inne ograniczenia, jak na przykład moc procesora.

Comments

Leave a response

  1. Ole about 3 hours later:

    To można wziąć kernel 64bit a całe userspace zostawić na 32bit. Linuks nie ma z tym najmniejszego problemu. Jeżeli jeden proces nie potrzebuje > 2GB to jest to dość dobre rozwiązanie.

  2. R about 22 hours later:

    Super artykuł, jak reszta tutaj. Ciekawy i dobrze przedstawiony. Może częściej byście coś opisywali?

  3. kmb 1 day later:

    strach się bać jak serwis by zasuwał gdyby go przenieść na platformę 16 bitową.. Demon szybkości! A gdyby jeszcze go napisać w asemblerze to już nawet boje się myśleć..

    A czy są jakieś badania o ile wydajniejsza jest arch. 64 bitowa?

  4. matt 1 day later:

    kmb, chyba kpisz prawda?

  5. ukasz 1 day later:

    Ole: testujemy wszystkie kombinacje, ale w naszym przypadku jajko 64 bitowe w praktyce nic nie zmieni

    kmb: jeśli chodzi o różnice w użyciu procesora to 32 bity zjadają około 5% procent więcej (sumarycznie przy quad corach) w stosunku do 64 bitów, tak więc na 64 bitach mamy ciut większy zapas mocy procesora ale nijak nie idzie go wykorzystać bo mamy za mało odpalonych procesów (ze względu na limit ramu)

  6. Marek Majkowski 1 day later:

    Ole: To można wziąć kernel 64bit a całe userspace zostawić na 32bit

    Przetestowaliśmy to. W praktyce nie ma znaczenia czy użyjemy jądra 32 bitowego z HIGHMEM64G czy 64 bitowego. Teoretycznie mogłoby mieć to znaczenie gdybyśmy chcieli poświęcić więcej niż 4GB RAMu na cache systemowy. Jednak aż tyle wolnej pamięci nie mamy.

    kmb: A czy są jakieś badania o ile wydajniejsza jest arch. 64 bitowa?

    W tym artykule skupiłem się bardziej na koszcie pamięciowym architektury 64 bitowej. Lecz jeśli chcesz znać moją opinię o wydajności…

    Z benchmarków wynika, że prędkość architektur i386 i x86_64 jest porównywalna. Niektóre benchmarki wskazują delikatną przewagę jednej inne drugiej architektury.

    Przykładowo znalazłem taki test, gdzie kompilacja kernela na 64 bitach wygląda szybciej: http://www.phoronix.com/scan.php?page=article&item=616&num=3

    Jednak jest to za mało by jednoznacznie stwierdzić przewagę tej architektury.

    64 bity teoretycznie powinny być szybsze, choćby ze względu na

    - szybsze operacje na 8 bajtowych intach

    - prostsze syscalle http://isomerica.net/archives/2007/05/28/what-is-linux-gateso1-and-why-is-it-missing-on-x86-64/

    - wiele zmian na poziomie assemblera (moja ulubiona różnica to nie odkladanie ebp na stos w przy skoku do funkcji) http://www.cs.cmu.edu/~fp/courses/15213-s06/misc/asm64-handout.pdf

    - konczac na detalach typu obsluga gettimeofday(), która na x86_64 nie wymaga syscalla http://www.ussg.iu.edu/hypermail/linux/kernel/0702.0/0082.html

  7. Widmo 4 days later:

    Więcej, więcej takich art’ów! :)

  8. fijal 8 days later:

    Na 32 bitach mozecie uzywac psyco (co prawda pamiec wam tylko od tego skoczy)

  9. anih 8 days later:

    czy moglibyscie opisac w jaki sposob django jest odpalone na poszczegolnych maszynach? bo jakos nie moge znalezc podobnego sposobu jak wasz w dokumentacji :)

  10. mariush 10 days later:

    Trzymajcie tak dalej, jako nieliczni dzielicie sie wiedza techniczna i to na dobrym poziomie. Az milo sie wraca i czyta takie rzeczy… :)

  11. tie 11 days later:

    a ja mam takie pytanie – do adminka :) – grono napisane jest w AJAX czy PHP ?

  12. anih 11 days later:

    OMG co ma AJAX do PHP ;/ grono jest napisane w django AJAX – Asynchronous JavaScript and XML PHP – jezyk skryptowy DJANGO – framework pythonowy

  13. climbus 13 days later:

    Cały czas nie kumam czemu Django nie jest oparte na wątkach. Przecież to spora oszczędność. Może trochę więcej pracy przy thread safe ale…

  14. Marek Majkowski 13 days later:

    climbus: Cały czas nie kumam czemu Django nie jest oparte na wątkach.

    Django to bardziej zbiór bibliotek. Jeśli mówimy o procesach/wątkach to mówimy nie o Django, ale o konkretnej implementacji serwera HTTP. Oczywiście serwer musi potrafić obsługiwać stos WSGI, tak żeby dało się go podpiąć do Django.

    My zdecydowaliśmy się na architekturę obsługującą WSGI w oparciu o procesy. Głównym argumentem za procesami nad wątkami jest Pythonowa architektura znana jako GIL (global interpreter lock). http://docs.python.org/api/threads.html Właśnie przez GIL w Pythonie w jednym procesie, bez względu na ilość wątków, nie da się wykorzystać więcej niż jednego procesora. W naszym przypadku użycie wątków nie daje większych zysków, poza zyskiem pamięci. Ze względu na GIL, używając wątków mielibyśmy gorszą responsywność. Jeśli jeden wątek będzie potrzebował dużo policzyć, to inne wątki będą czekały.

    Istnieją implementacje Pythona bez GILa, jak na przykład Stackless Python. Jednak wdrożenie tego byłoby bardzo skomplikowane, wymagałoby dostosowania Stacklessa i przepisania Grona :)

  15. frrua 14 days later:

    “AJAX” to przestarzały i mało trafny akronim. Współczesna nazwa dla tej technologii to “Ajax” (wielkość użytych liter makes the difference) i jest to nazwa, która nie implikuje czy mamy do czynienia z połączeniem synchronicznym, czy asynchronicznym ani czy używamy XML-a, czy nie ;)

  16. R 14 days later:

    Marek, a zakładając że przepisalibyście grono i korzystali ze stackless pythona, jak duże korzyści systemowe moglibyście odnieść? Czy korzystanie z wątków jest wyraźnie widoczne po przekroczeniu pewnego progu odwiedzalności serwisu?

  17. anih 14 days later:

    czy dobrze mi sie wydaje ze watki i procesy w linuxie maja podobna wydajnosc jesli chodzi o procesor, a tylko mniej ramu moga zrzerac?

  18. climbus 14 days later:

    1. Słyszałem (nie sprawdzałem), że Django nie jest thread safe. 2. Czy robiliście testy. Aplikacje webowe raczej nie mają skomplikowanej logiki i liczenia nie jest zbyt wiele. Ciekawi mnie jaka była by różnica. 3, Czy rozpatrywaliście wariant pomiędzy: kilka procesów po kilka wątków (teoretyzuję). 4. Ile mniej więcej procesów przypada na jedną maszynę?

  19. matrut 15 days later:

    temat zastosowania fork()’a i watkow w odniesieniu do aplikacji serwerowych byl poruszany wiele razy

    z reszta jest temu poswiecony jest art. (http://www.kegel.com/c10k.html)

    mowienie co jest lepsze – watki czy procesy ma sens w odniesieniu do konkretnej architektury, os’a, a nawet stricto zadanej aplikacji

    wg. mnie uzywanie watkow w linuxie jak i (free | open)bsd nie przynosi zyskow a wrecz kaplikuje rozwoj aplikacji serwerowej

    smialbym twierdzic, ze mimo powszechnego zachwalania freebsd pod katem wydajnosci port biblioteki libpth byl b. opozniony w stosunku do wersji linuxowej

    opnie znanych:

    wg. ksiazki richarda stevensa ‘unix – programowanie uslug sieciowych’ – w rozdziale poswieconym architekturze aplikacji serwerowych podkreslone sa zalety wielowatkowego wyprzedzajacego serwera tcp. warto dodac, ze autor swego rodzaju biblii dla developerow uzywal komercyjncyh wersji unix’a a stan wiedzy datowany jest na koneic lat ‘90.

    zdaniem Steva Jurczyka – autora IdeaWebServer ktory zachwala swoje rozwiazanie jako jedno z bardziej wydajnych – hybrydka fork’a + kqueue ; wspomnial o magicznej liczbie 10 000 polaczen ktore IdeaWebSerer jest w stanie obsluzyc (nie wnikajac przy tym w szczegoly)

    wiec wniosek jeden – jesli mowa o wydajnych aplikacjach serv. pod katem optymalizacji dla Linux’a – fork() & /dev/poll dla jader 2.6 i real time signals + fork() dla jader 2.4

    ciekawe jestem jak wyglada sprawa wydajnosci watkow pod solarisem

  20. Marek Majkowski 21 days later:

    fijal: Na 32 bitach mozecie uzywac psyco

    Bardzo dobra uwaga. Jesli zacznie nam brakować procesora, to Psyco będzie dla nas bardzo ważne.

    R: Marek, a zakładając że przepisalibyście grono i korzystali ze stackless pythona, jak duże korzyści systemowe moglibyście odnieść?

    Potencjalnie moglibyśmy oszczędzić sporo RAMu na procesach (nasze procesy używają stosunkowo mało procesora, więc gdyby udało się “złączyć” wiele procesów w jeden, używając wątków)

    anih: czy dobrze mi sie wydaje ze watki i procesy w linuxie maja podobna wydajnosc jesli chodzi o procesor, a tylko mniej ramu moga zrzerac?

    Tak, ale jak już mówiłem problem tkwi w interpreterze Pythona (w mechanizmie GIL).

    climbus: 1. Słyszałem (nie sprawdzałem), że Django nie jest thread safe.

    Nie wiem, używamy procesów. Nawet jeśli Django nie jest thread safe, to naprawa tego nie byłaby taka trudna.

    climbus: 2. Czy robiliście testy. Aplikacje webowe raczej nie mają skomplikowanej logiki i liczenia nie jest zbyt wiele. Ciekawi mnie jaka była by różnica.

    Zalety wątków: mniej zużytego RAMu. Wady wątków: proces Pythona przez GIL nie może używać więcej niż jednego procesora, więc rośnie nam latencja. Jeśli jeden request obsługiwany przez jeden wątek używa procesora, to inne wątki muszą czekać.

    climbus: 3, Czy rozpatrywaliście wariant pomiędzy: kilka procesów po kilka wątków (teoretyzuję).

    Istnieje taka możliwość, ale póki starcza nam RAMu, puty będziemy bazować na procesach. Wiemy, że to podejście działa.

    climbus: 4. Ile mniej więcej procesów przypada na jedną maszynę

    Wolimy nie mówić o detalach w naszej serwerowni. W artykule podałem kilka numerków, można z nich conieco wyliczyć :)

    matrut: wiec wniosek jeden – jesli mowa o wydajnych aplikacjach serv. pod katem optymalizacji dla Linux’a – fork() & /dev/poll dla jader 2.6 i real time signals + fork() dla jader 2.4

    Moim zdaniem znacznie wdzięczniejszy od RTSignals jest epoll(). Ale to nie w tym tkwi sedno. Czasem aplikacje łatwiej się buduje w oparciu o wątki, czasem o procesy, a czasem o biblioteki asynchroniczne typu libevent. Nie ma idealnego rozwiązania dla wszystkich aplikacji. U nas naturalną drogą jest oparcie architektury o procesy i to po prostu działa. Jak wszystko, ma to swoje wady, ma swoje zalety.

  21. anih 23 days later:

    co do psyco to jest ono jeszcze na tyle niedopracowane ze jesli wlaczy sie optymalizacje calego django tzn wszystkich funkcji to nawet nie odpalimy django w trybie testowym(python manage.py runserver). jesli wybierzemy tylko czesc funkcji to django jest tylko “lekko” niestabilne wiec trzeba bardzo uwazac gdzie sie uzywa optymalizacji psyco, mozna probowac podpiac psyco pod funkcje odpowiedzialne za templaty to powinno dac niezlego kopa przynajmniej tak twierdza deweloperzy psyco

Comments