Postgres w pamięci RAM – tips&tricks

RAM tips&tricks

W wydaniu 9.4 PostgreSQL pojawił się nowy, istotny parametr w postgresql.conf a mianowicie huge_pages (enum). Jeśli twój system ma do dyspozycji wiele gigabajtów, a nawet terabajty RAM-u, albo/i cierpi z powodu przeciążonych procesorów lub też zastanawiasz się jak uniemożliwić mu swapowanie ten artykuł jest właśnie dla ciebie.

Teoria

Systemy używające mechanizmu pamięci wirtualnej nie są niczym nowym, mało kto pamięta czasy gdy systemy odwoływały się bezpośrednio do pamięci fizycznej. Teraz każdy proces ma przyporządkowaną własną przestrzeń pamięci, która jest mapowana do pamięci fizycznej. Taki mechanizm umożliwia przypisanie różnych danych do tego samego adresu wirtualnego, który jest tłumaczony na unikatowy adres pamięci fizycznej.

Proces zwykle wygląda następująco: system operacyjny zarządza tablicą stron pamięci, podczas gdy za tłumaczenie adresów odpowiada sprzęt. Niestety proces nie należy do najtańszych a konieczne jest jego wykonanie przy każdym dostępie do pamięci. Na szczęście został utworzony mały bufor przechowujący tłumaczenia ostatnio używanych adresów – Translation Lookaside Buffer (TLB). TLB jest zazwyczaj niewielkich rozmiarów zawiera do 100 wpisów ponieważ musi być przynajmniej tak szybki jak L1 jeśli nie szybszy. Dla wielu systemów, zwłaszcza przetwarzających duże ilości danych, będzie to oznaczało konieczność wielokrotnego przechodzenia pełnego procesu tłumaczenia zamiast znacznie szybszego odczytu danych z TLB.

Ponieważ nie możemy (nie chcemy) powiększać TLB możemy powiększyć strony! Zwiększony rozmiar stron oznacza szybsze przeszukiwanie tablicy stron pamięci z prostego powodu – jej mniejszego rozmiaru. Większość sprzętu dostępnego na rynku standardowo pracuje na stronach o rozmiarze 4K, a poza nimi umożliwia posługiwanie się “wielkimi” stronami o rozmiarach 2M i 1G (w zależności od architektury, tutaj podano dane dla architektury x86).

W świecie Linuxa istnieją co najmniej dwa sposoby na “powiększenie” stron:

W tym artykule omówimy pierwszy ze sposobów, ponieważ właśnie jego obsługa została zaimplementowana w postgresie.

Zalety

  • odciążenie CPU – skrócenie czasu potrzebnego na zarządzanie pamięcią.
  • “Przypięcie” shared buffers do RAM-u (sztuczka uniemożliwiająca swapowanie shared buffers).
  • Bardziej wydajne zarządzanie pamięcią w systemach z dużą ilością RAM-u.

Konfiguracja

Pierwszym krokiem jest sprawdzenie czy nasz kernel ma ustawione następujące flagi:
CONFIG_HUGETLBFS=y
CONFIG_HUGETLB_PAGE=y

Możemy to zweryfikować następującym poleceniem:
grep HUGETLB /boot/config-$(uname -r)
Przykładowy, poprawny wynik:
CONFIG_ARCH_WANT_GENERAL_HUGETLB=y
CONFIG_CGROUP_HUGETLB=y
CONFIG_HUGETLBFS=y
CONFIG_HUGETLB_PAGE=y

Jeśli tak (jak większość nowych systemów) możemy przystąpić do szacowania liczby potrzebnych huge pages. Dobrą estymatą jest sprawdzenie wartości VmPeak postmastera a następnie podzielenie jej przez rozmiar “dużej” strony.
$ head -1 $PGDATA/postmaster.pid
4170
$ grep ^VmPeak /proc/4170/status
VmPeak: 6490428 kB
$ grep ^Hugepagesize /proc/meminfo
Hugepagesize: 2048 kB
6490428 kB / 2048 kB = 3169.154.

Potrzebujemy więc co najmniej 3170 huge pages, które możemy ustawić następująco:
$ sysctl -w vm.nr_hugepages=3170
Jeśli chcemy aby nasze rozwiązanie było persystentne należy dodać je do
/etc/sysctl.conf
Dla pewności zmieniamy wartość huge_pages w pliku konfiguracyjnym postgresa postgresql.conf na “on”. Restartujemy postgresa. Jeśli pojawi się błąd bardzo możliwe, że system nie mógł zaalokować wystarczająco dużego, ciągłego obszaru pamięci i konieczny jest restart systemu.

Test

Następnie sprawdzamy czy system zaczął używać “wielkich” stron:
$ grep Huge /proc/meminfo
Co to oznacza?
HugePages_Total: 2090
HugePages_Free: 1358
HugePages_Rsvd: 1341

  • 2090-1358 = 732 strony są aktualnie używane,
  • 1341 stron jest zarezerwowanych,
  • 1358 – 1341 = 17 stron nigdy nie zostanie użytych,
  • w skrócie, liczbę stron, które są lub będą mogły zostać użyte można obliczyć następująco:
    HugePages_Total - HugePages_Free + HugePages_Rsvd

Ostrzeżenia

Nie marnuj pamięci!

Jeśli wartość HugePages_Free nie jest znacząco mniejsza od HugePages_Total, np. jak w przykładzie poniżej:
grep Huge /proc/meminfo
przykładowy wynik:
HugePages_Total: 142
HugePages_Free: 130
HugePages_Rsvd: 0
HugePages_Surp: 0

Postgres jest już uruchomiony od jakiegoś czasu – zmniejsz liczbę huge pages w systemie:
echo mniejsza_wartosc > /proc/sys/vm/nr_hugepages
Dynamiczne zwiększanie ilości huge pages nie zadziała zawsze, ponieważ wolna pamięć mogła już ulec fragmentacji, natomiast zmniejszanie zadziała zawsze.

Siódemki są bezpieczne

Jeśli wciąż używasz systemu Red Hat/CentOS 6 (szczególnie 6.0 lub 6.1), SLES11, OEL6, UEK2 albo niższych zrób porządne testy przed włączeniem opcji huge_pages w PostgreSQL albo zrezygnuj z tej metody optymalizacji. W tych wersjach użycie huge pages powodowało problemy z CPU. Dla CentOS 7 lub Red Hat 7 użycie huge pages jest zalecane.

Tags

top