Pag-optimize sa Linux upang mahawakan ang 1.2 milyong mga kahilingan sa JSON bawat segundo

Ang isang detalyadong gabay ay nai-publish sa pag-tune sa kapaligiran ng Linux upang makamit ang maximum na pagganap para sa pagproseso ng mga kahilingan sa HTTP. Ang mga iminungkahing pamamaraan ay naging posible upang mapataas ang pagganap ng JSON processor batay sa libreactor library sa Amazon EC2 environment (4 vCPU) mula sa 224 na libong mga kahilingan sa API bawat segundo na may mga karaniwang setting ng Amazon Linux 2 na may kernel 4.14 hanggang 1.2 milyong kahilingan bawat pangalawa pagkatapos ng pag-optimize (isang pagtaas ng 436%), at humantong din sa pagbawas sa mga pagkaantala sa pagproseso ng mga kahilingan ng 79%. Ang mga iminungkahing pamamaraan ay hindi partikular sa libreactor at gumagana kapag gumagamit ng iba pang mga http server, kabilang ang nginx, Actix, Netty at Node.js (libreactor ay ginamit sa mga pagsubok dahil ang solusyon batay dito ay nagpakita ng mas mahusay na pagganap).

Pag-optimize sa Linux upang mahawakan ang 1.2 milyong mga kahilingan sa JSON bawat segundo

Mga pangunahing pag-optimize:

  • Pag-optimize ng libreactor code. Ang opsyon na R18 mula sa Techmpower kit ay ginamit bilang batayan, na pinahusay sa pamamagitan ng pag-alis ng code upang limitahan ang bilang ng mga CPU core na ginamit (pinapayagan ng optimization na mapabilis ang trabaho ng 25-27%), na nag-assemble sa GCC gamit ang mga opsyon na "-O3". (isang pagtaas ng 5-10%) at "-march-native" (5-10%), pinapalitan ang read/write na mga tawag ng recv/send (5-10%) at binabawasan ang overhead kapag gumagamit ng mga pthread (2-3%) . Ang kabuuang pagtaas ng performance pagkatapos ng pag-optimize ng code ay 55%, at tumaas ang throughput mula 224k req/s hanggang 347k req/s.
  • Huwag paganahin ang proteksyon laban sa mga kahinaan sa speculative execution. Gamit ang mga parameter na β€œnospectre_v1 nospectre_v2 pti=off mds=off tsx_async_abort=off” kapag nilo-load ang kernel na pinapayagang pataasin ang performance ng 28%, at tumaas ang throughput mula 347k req/s hanggang 446k req/s. Hiwalay, ang pagtaas mula sa parameter na "nospectre_v1" (proteksyon mula sa Spectre v1 + SWAPGS) ay 1-2%, "nospectre_v2" (proteksyon mula sa Spectre v2) - 15-20%, "pti=off" (Spectre v3/Meltdown) - 6 %, "mds=off tsx_async_abort=off" (MDS/Zombieload at TSX Asynchronous Abort) - 6%. Ang mga setting para sa proteksyon laban sa L1TF/Foreshadow (l1tf=flush), iTLB multihit, Speculative Store Bypass at mga pag-atake ng SRBDS ay pinabayaang hindi nabago, na hindi nakaapekto sa performance dahil hindi sila nakipag-intersect sa nasubok na configuration (halimbawa, partikular sa KVM, nested virtualization at iba pang mga modelo ng CPU).
  • Hindi pagpapagana ng pag-audit at pag-block ng mga mekanismo ng system call gamit ang command na "auditctl -a never,task" at tinukoy ang opsyong "--security-opt seccomp=unconfined" kapag sinimulan ang docker container. Ang kabuuang pagtaas ng performance ay 11%, at tumaas ang throughput mula 446k req/s hanggang 495k req/s.
  • Hindi pagpapagana ng mga iptable/netfilter sa pamamagitan ng pag-unload ng mga nauugnay na kernel module. Ang ideya na huwag paganahin ang firewall, na hindi ginamit sa isang partikular na solusyon sa server, ay na-prompt ng mga resulta ng pag-profile, kung saan ang nf_hook_slow function ay tumagal ng 18% ng oras upang maisakatuparan. Napansin na ang mga nftable ay gumagana nang mas mahusay kaysa sa mga iptable, ngunit ang Amazon Linux ay patuloy na gumagamit ng mga iptable. Pagkatapos i-disable ang mga iptable, ang pagtaas ng performance ay 22%, at tumaas ang throughput mula 495k req/s hanggang 603k req/s.
  • Binawasan ang paglipat ng mga humahawak sa pagitan ng iba't ibang mga core ng CPU upang mapabuti ang kahusayan ng paggamit ng cache ng processor. Ang pag-optimize ay isinagawa kapwa sa antas ng mga nagbubuklod na proseso ng libreactor sa mga core ng CPU (CPU Pinning) at sa pamamagitan ng pag-pin sa mga humahawak ng kernel network (Receive Side Scaling). Halimbawa, ang irqbalance ay hindi pinagana at ang queue affinity sa CPU ay tahasang itinakda sa /proc/irq/$IRQ/smp_affinity_list. Upang magamit ang parehong CPU core upang iproseso ang proseso ng libreactor at ang network queue ng mga papasok na packet, isang custom na BPF handler ang ginagamit, na konektado sa pamamagitan ng pagtatakda ng SO_ATTACH_REUSEPORT_CBPF flag kapag gumagawa ng socket. Upang itali ang mga pila ng mga papalabas na packet sa CPU, ang mga setting /sys/class/net/eth0/queues/tx- ay binago /xps_cpus. Ang kabuuang pagtaas ng performance ay 38%, at tumaas ang throughput mula 603k req/s hanggang 834k req/s.
  • Pag-optimize ng interrupt na paghawak at paggamit ng botohan. Ang pag-enable sa adaptive-rx mode sa ENA driver at pagmamanipula sa sysctl net.core.busy_read ay nagpapataas ng performance ng 28% (nadagdagan ang throughput mula 834k req/s hanggang 1.06M req/s, at bumaba ang latency mula 361ΞΌs hanggang 292ΞΌs).
  • Hindi pagpapagana ng mga serbisyo ng system na humahantong sa hindi kinakailangang pagharang sa network stack. Ang hindi pagpapagana sa dhclient at manu-manong pagtatakda ng IP address ay nagresulta sa 6% na pagtaas ng performance at ang throughput ay tumaas mula 1.06M req/s hanggang 1.12M req/s. Ang dahilan kung bakit nakakaapekto ang dhclient sa pagganap ay sa pagsusuri ng trapiko gamit ang isang raw socket.
  • Labanan ang Spin Lock. Ang paglipat ng network stack sa "noqueue" mode sa pamamagitan ng sysctl "net.core.default_qdisc=noqueue" at "tc qdisc replace dev eth0 root mq" ay humantong sa isang 2% na pagtaas ng performance, at ang throughput ay tumaas mula 1.12M req/s hanggang 1.15M req/s.
  • Panghuling minor optimization, gaya ng hindi pagpapagana ng GRO (Generic Receive Offload) gamit ang command na β€œethtool -K eth0 gro off” at pagpapalit ng cubic congestion control algorithm ng reno gamit ang sysctl β€œnet.ipv4.tcp_congestion_control=reno”. Ang kabuuang pagtaas ng produktibo ay 4%. Tumaas ang throughput mula 1.15M req/s hanggang 1.2M req/s.

Bilang karagdagan sa mga pag-optimize na gumana, tinatalakay din ng artikulo ang mga pamamaraan na hindi humantong sa inaasahang pagtaas ng pagganap. Halimbawa, ang mga sumusunod ay naging hindi epektibo:

  • Ang pagpapatakbo ng libreactor nang hiwalay ay hindi naiiba sa pagganap mula sa pagpapatakbo nito sa isang lalagyan. Ang pagpapalit ng writev ng send, pagpapataas ng mga maxevent sa epoll_wait, at pag-eksperimento sa mga bersyon at flag ng GCC ay walang epekto (ang epekto ay kapansin-pansin lamang para sa mga flag na "-O3" at "-march-native").
  • Ang pag-upgrade ng Linux kernel sa bersyon 4.19 at 5.4, gamit ang SCHED_FIFO at SCHED_RR scheduler, pagmamanipula ng sysctl kernel.sched_min_granularity_ns, kernel.sched_wakeup_granularity_ns, transparent_hugepages=never, skew_tick=1 at clocksource=tsc did not affect performance=tsc
  • Sa driver ng ENA, walang epekto ang pag-enable sa mga Offload mode (segmentation, scatter-gather, rx/tx checksum), pagbuo gamit ang flag na "-O3", at paggamit ng ena.rx_queue_size at ena.force_large_llq_header.
  • Ang mga pagbabago sa network stack ay hindi nagpabuti ng pagganap:
    • Huwag paganahin ang IPv6: ipv6.disable=1
    • Huwag paganahin ang VLAN: modprobe -rv 8021q
    • Huwag paganahin ang pagsuri sa source ng package
      • net.ipv4.conf.all.rp_filter=0
      • net.ipv4.conf.eth0.rp_filter=0
      • net.ipv4.conf.all.accept_local=1 (negatibong epekto)
    • 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

    Pinagmulan: opennet.ru

Magdagdag ng komento