Оптимизација на Linux за справување со 1.2 милиони JSON барања во секунда

Објавен е детален водич за подесување на околината на Linux за да се постигнат максимални перформанси за обработка на барањата HTTP. Предложените методи овозможија да се зголемат перформансите на JSON процесорот базиран на библиотеката libreactor во околината на Amazon EC2 (4 vCPU) од 224 илјади API барања во секунда со стандардни поставки на Amazon Linux 2 со јадро 4.14 на 1.2 милиони барања по второ по оптимизацијата (зголемување од 436%), а исто така доведе до намалување на доцнењата во обработката на барањата за 79%. Предложените методи не се специфични за libreactor и работат при користење на други http сервери, вклучувајќи ги nginx, Actix, Netty и Node.js (libreactor се користеше во тестовите бидејќи решението базирано на него покажа подобри перформанси).

Оптимизација на Linux за справување со 1.2 милиони JSON барања во секунда

Основни оптимизации:

  • Оптимизирање на кодот на ослободувачот. Како основа се користеше опцијата R18 од комплетот Techempower, која беше подобрена со отстранување на кодот за да се ограничи бројот на користени јадра на процесорот (оптимизацијата овозможи забрзување на работата за 25-27%), склопувајќи се во GCC со опциите „-O3“ (зголемување од 5-10%) и „-марш-мајчин“ (5-10%), заменувајќи ги повиците за читање/запишување со recv/send (5-10%) и намалување на трошоците при користење на нишки (2-3%) . Целокупното зголемување на перформансите по оптимизацијата на кодот беше 55%, а пропусната моќ се зголеми од 224k req/s на 347k req/s.
  • Оневозможи заштита од шпекулативни пропусти при извршувањето. Користењето на параметрите „nospectre_v1 nospectre_v2 pti=off mds=off tsx_async_abort=off“ при вчитување на кернелот овозможи да се зголемат перформансите за 28%, а пропусната моќ се зголеми од 347k req/s на 446k req/s. Одделно, зголемувањето од параметарот „nospectre_v1“ (заштита од Spectre v1 + SWAPGS) беше 1-2%, „nospectre_v2“ (заштита од Spectre v2) - 15-20%, „pti=off“ (Spectre v3/Meltdown) - 6 %, "mds=off tsx_async_abort=off" (MDS/Zombieload и TSX асинхрон прекин) - 6%. Поставките за заштита од L1TF/Foreshadow (l1tf=flush), iTLB multihit, Speculative Store Bypass и SRBDS напади беа оставени непроменети, што не влијаеше на перформансите бидејќи тие не се вкрстуваат со тестираната конфигурација (на пример, специфични за KVM, вгнездени виртуелизација и други модели на процесори).
  • Оневозможување на механизмите за ревизија и блокирање на системски повици со помош на командата „auditctl -a never,task“ и специфицирање на опцијата „--security-opt seccomp=unconfined“ при стартување на докер-контејнерот. Целокупното зголемување на перформансите беше 11%, а пропусната моќ се зголеми од 446k req/s на 495k req/s.
  • Оневозможување на iptables/netfilter со растоварување на поврзаните модули на кернелот. Идејата да се оневозможи заштитниот ѕид, кој не се користеше во одредено решение за серверот, беше поттикната од резултатите од профилирањето, судејќи според кои на функцијата nf_hook_slow и беа потребни 18% од времето за извршување. Забележано е дека nftables работи поефикасно од iptables, но Amazon Linux продолжува да користи iptables. По оневозможувањето на iptables, зголемувањето на перформансите беше 22%, а пропусната моќ се зголеми од 495k req/s на 603k req/s.
  • Намалена миграција на ракувачи помеѓу различни јадра на процесорот за да се подобри ефикасноста на употребата на кешот на процесорот. Оптимизацијата беше спроведена и на ниво на врзување на процесите на ослободувачот на јадрата на процесорот (Прикачување на процесорот) и преку прикачување на ракувачи на мрежата на јадрото (Речеиво странично скалирање). На пример, irqbalance беше оневозможен и афинитетот на редицата кон процесорот беше експлицитно поставен во /proc/irq/$IRQ/smp_affinity_list. За да се користи истото јадро на процесорот за обработка на процесот на ослободување и мрежната редица на дојдовни пакети, се користи прилагоден управувач за BPF, поврзан со поставување на знамето SO_ATTACH_REUSEPORT_CBPF при креирањето на штекерот. За да се поврзат редици од појдовни пакети со процесорот, поставките /sys/class/net/eth0/queues/tx- се сменети /xps_cpus. Целокупното зголемување на перформансите беше 38%, а пропусната моќ се зголеми од 603k req/s на 834k req/s.
  • Оптимизација на ракување со прекини и користење на гласање. Овозможувањето на режимот приспособлив-rx во двигателот ENA и манипулирањето со sysctl net.core.busy_read ги зголеми перформансите за 28% (пропусната моќ се зголеми од 834k req/s на 1.06M req/s, а латентноста се намали од 361μs на 292μs).
  • Оневозможување на системските услуги што доведуваат до непотребно блокирање во мрежниот оџак. Оневозможувањето на dhclient и рачното поставување на IP адресата резултираше со зголемување на перформансите за 6%, а пропусната моќ се зголеми од 1.06M req/s на 1.12M req/s. Причината зошто dhclient влијае на перформансите е анализата на сообраќајот со користење на необработен приклучок.
  • Борба против спин заклучување. Префрлањето на магацинот на мрежата во режим „noqueue“ преку sysctl „net.core.default_qdisc=noqueue“ и „tc qdisc replace dev eth0 root mq“ доведе до зголемување на перформансите за 2%, а пропусната моќ се зголеми од 1.12 M req/s на 1.15M бара/и.
  • Конечни помали оптимизации, како што е оневозможување на GRO (Generic Receive Offload) со командата „ethtool -K eth0 gro off“ и замена на алгоритам за контрола на кубната конгестија со reno користејќи sysctl „net.ipv4.tcp_congestion_control=reno“. Вкупниот пораст на продуктивноста беше 4%. Пропусната моќ се зголеми од 1.15 милиони барања/сек на 1.2 милиони барања/сек.

Покрај оптимизациите што функционираа, написот ги разгледува и методите што не доведоа до очекуваното зголемување на перформансите. На пример, следново се покажа како неефикасно:

  • Работењето на либреактор одделно не се разликуваше во перформансите од неговото водење во контејнер. Замената на writev со испраќање, зголемувањето на максимумите во epoll_wait и експериментирањето со верзии и знамиња на GCC немаше ефект (ефектот беше забележлив само за знаменцата „-O3“ и „-марш-мајчин“).
  • Надградбата на кернелот на Linux до верзии 4.19 и 5.4, користење на распоредувачите SCHED_FIFO и SCHED_RR, манипулирање со sysctl kernel.sched_min_granularity_ns, kernel.sched_wakeup_granularity_ns, transparent_hugepages=never, skew_tick=1 и c не влијаеше на перформансите на изворот.
  • Во двигателот ENA, овозможувањето на режимите за Offload (сегментација, расфрлање-собира, проверка на rx/tx), градењето со знаменцето „-O3“ и користењето на параметрите ena.rx_queue_size и ena.force_large_llq_header немаше ефект.
  • Промените во мрежниот оџак не ги подобрија перформансите:
    • Оневозможи IPv6: ipv6.disable=1
    • Оневозможи VLAN: modprobe -rv 8021q
    • Оневозможи проверка на изворот на пакетот
      • net.ipv4.conf.all.rp_filter=0
      • net.ipv4.conf.eth0.rp_filter=0
      • net.ipv4.conf.all.accept_local=1 (негативен ефект)
    • 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

    Извор: opennet.ru

Додадете коментар