Bol sprístupnený podrobný sprievodca optimalizáciou prostredia Linux na dosiahnutie maximálnych výkonových výsledkov spracovania HTTP požiadaviek. Navrhnuté metódy umožnili zvýšiť výkon spracovateľa JSON, založeného na knižnici libreactor, v prostredí Amazon EC2 (4 vCPU) z 224 tisíc API požiadaviek za sekundu pri štandardných nastaveniach Amazon Linux 2 s jadrom 4.14 na 1,2 milióna požiadaviek za sekundu po optimalizácii (zvýšenie o 436 %), ako aj znížiť latenciu pri spracovaní požiadaviek o 79 %. Navrhnuté metódy nie sú špecifické pre libreactor a fungujú aj pri využití iných HTTP serverov, vrátane nginx, Actix, Netty a Node.js (libreactor bol použitý v testoch, pretože riešenie založené na ňom preukázalo najlepší výkon).

Hlavné optimalizácie:
- Optimalizácia kódu libreactor. Ako základ bol použitý variant R18 z kolekcie Techempower, ktorý bol vylepšený odstránením kódu na obmedzenie počtu používaných CPU jadier (optimalizácia umožnila urýchliť výkon o 25-27 %), zostavením v GCC s voľbami "-O3" (zvýšenie o 5-10 %) a "-march-native" (5-10 %), výmenou volaní read/write na recv/send (5-10 %) a znížením režijných nákladov pri použití pthreads (2-3 %). Celkové zvýšenie výkonu po optimalizácii kódu predstavovalo 55 %, pričom priepustnosť vzrástla z 224k req/s na 347k req/s.
- Vypnutie ochrany pred zraniteľnosťami spôsobenými špekulatívnym vykonávaním inštrukcií. Použitie parametrov pri načítaní jadra "nospectre_v1 nospectre_v2 pti=off mds=off tsx_async_abort=off" umožnilo zvýšiť výkon o 28 %, pričom priepustnosť vzrástla z 347k req/s na 446k req/s. Zvýšenie výkonnosti za jednotlivé parametre "nospectre_v1" (ochrana pred Spectre v1 + SWAPGS) sa pohybovalo od 1-2 %, "nospectre_v2" (ochrana pred Spectre v2) – 15-20 %, "pti=off" (Spectre v3/Meltdown) – 6 %, "mds=off tsx_async_abort=off" (MDS/Zombieload a TSX Asynchronous Abort) – 6 %. Nastavenia na ochranu pred útokmi L1TF/Foreshadow (l1tf=flush), iTLB multihit, Speculative Store Bypass a SRBDS zostali nezmenené, pretože nemali vplyv na výkon, keďže sa neprekrývali s testovanou konfiguráciou (napríklad, sú špecifické pre KVM, vnorenú virtualizáciu a iné modely CPU).
- Vypnutie mechanizmov auditu a blokovania systémových volaní pomocou príkazu "auditctl -a never,task" a nastavením voľby "–security-opt seccomp=unconfined" pri spustení kontajnera docker. Celkové zvýšenie výkonu predstavovalo 11 %, pričom priepustnosť vzrástla z 446k req/s na 495k req/s.
- Vypnutie iptables/netfilter prostredníctvom odinštalovania súvisiacich modulov jadra. K myšlienke vypnúť firewall, ktorý nebol používaný v špecifickom serverovom riešení, odporučili výsledky profilovania, podľa ktorých na vykonanie funkcie nf_hook_slow išlo 18% času. Uvádza sa, že nftables funguje efektívnejšie ako iptables, ale v Amazon Linux sa stále používa iptables. Po vypnutí iptables nárast výkonu dosiahol 22% a priepustnosť vzrástla z 495k req/s na 603k req/s.
- Zníženie migrácie spracovateľov medzi rôznymi jadrami CPU pre zvýšenie efektívnosti využívania procesorového cache. Optimalizácia bola vykonaná na úrovni priradenia procesov libreactor k jadrám CPU (CPU Pinning), ako aj prostredníctvom priradenia sieťových spracovateľov jadra (Receive Side Scaling). Napríklad bola vykonaná deaktivácia irqbalance a explicitné nastavenie priradení frontov k CPU v /proc/irq/$IRQ/smp_affinity_list. Pre použitie toho istého jadra CPU na spracovanie procesu libreactor a sieťového frontu prichádzajúcich paketov bol použitý vlastný BPF spracovateľ pripojený prostredníctvom nastavenia príznaku SO_ATTACH_REUSEPORT_CBPF pri vytváraní soketu. Pre priradenie k CPU frontov odchádzajúcich paketov boli zmenené nastavenia /sys/class/net/eth0/queues/tx-<n>/xps_cpus. Celkový nárast výkonu dosiahol 38% a priepustnosť vzrástla z 603k req/s na 834k req/s.
- Optimalizácia spracovania prerušenia a využitie polingu (polling). Aktivácia režimu adaptive-rx v ovládači ENA a manipulácie so sysctl net.core.busy_read umožnili zvýšiť výkon o 28% (priepustnosť vzrástla z 834k req/s na 1.06M req/s a oneskorenia klesli z 361μs na 292μs).
- Vypnutie systémových služieb, ktoré vedú k zbytočným blokovaniu v sieťovom stacku. Vypnutie dhclient a nastavenie IP adresy ručne viedlo k zvýšeniu výkonu o 6% a priepustnosť vzrástla z 1.06M req/s na 1.12M req/s. Dôvod vplyvu dhclient na výkon v analýze prevádzky pomocou raw-soketu.
- Boj so Spin Lock. Prevedenie sieťového stacku do režimu "noqueue" cez sysctl "net.core.default_qdisc=noqueue" a "tc qdisc replace dev eth0 root mq" viedlo k zvýšeniu výkonu o 2% a priepustnosť vzrástla z 1.12M req/s na 1.15M req/s.
- Finálne malé optimalizácie, ako je vypnutie GRO (Generic Receive Offload) príkazom „ethtool -K eth0 gro off“ a zmena algoritmu riadenia preťaženia z cubic na reno pomocou sysctl „net.ipv4.tcp_congestion_control=reno“. Celkový nárast výkonu dosiahol 4 %. Priepustnosť vzrástla z 1.15M req/s na 1.2M req/s.
Okrem vykonaných optimalizácií sa v článku zaoberajú aj metódy, ktoré nepriniesli očakávaný nárast výkonu. Napríklad sa ukázali ako neúčinné:
- Samostatný beh libreactor nemal odlišný výkon od spustenia v kontajneri. Vplyv nemala ani zmena writev na send, zvýšenie maxevents v epoll_wait, experimenty s verziami a flagmi GCC (efekt bol zaznamenaný len pre flagy „-O3“ a „-march-native“).
- Na výkon neovplyvnila aktualizácia jadra Linux na verzie 4.19 a 5.4, používanie plánovačov SCHED_FIFO a SCHED_RR, manipulácie so sysctl kernel.sched_min_granularity_ns, kernel.sched_wakeup_granularity_ns, transparent_hugepages=never, skew_tick=1 a clocksource=tsc.
- V ovládači ENA neovplyvnila aktivácia režimov Offload (segmentácia, scatter-gather, rx/tx kontrola súčtu), kompilácia s flagom „-O3“ a uplatnenie parametrov ena.rx_queue_size a ena.force_large_llq_header.
- Zmeny v sieťovom zásobníku neviedli k zvýšeniu výkonu:
- Vypnutie IPv6: ipv6.disable=1
- Vypnutie VLAN: modprobe -rv 8021q
- Vypnutie kontroly zdroja paketu
- net.ipv4.conf.all.rp_filter=0
- net.ipv4.conf.eth0.rp_filter=0
- net.ipv4.conf.all.accept_local=1 (negatívny efekt)
- net.ipv4.tcp_sack=0
- net.ipv4.tcp_dsack=0
- net.ipv4.tcp_mem/tcp_wmem/tcp_rmem
- net.core.netdev_budget
- net.core.dev_weight
- net.core.netdev_max_backlog
- net.ipv4.tcp_slow_start_after_idle=0
- net.ipv4.tcp_moderate_rcvbuf=0
- net.ipv4.tcp_timestamps=0
- net.ipv4.tcp_low_latency=1
- SO_PRIORITY
- TCP_NODELAY
Zdroj: opennet.ru
