5 ポイント 投稿者 GN⁺ 2024-07-29 | 1件のコメント | WhatsAppで共有
  • Linuxのネットワーク性能チューニングは、パケットが NICリングバッファ、IRQ、NAPI、softIRQ、qdisc、TCPバッファを経てアプリケーションソケットに到達する流れを、ボトルネック基準で解釈する作業である
  • 受信経路では、NICがDMAでパケットをRAMに書き込み、HardIRQを発生させ、ドライバがNAPIを予約して NET_RX_SOFTIRQ でリングバッファを空にした後、IP/TCP層とソケット受信バッファへ渡す
  • ethtool/proc/net/softnet_statssnetstatsysctl は観察と調整の出発点であり、割り込み統合、IRQ affinity、RSS/RPS/RFS/aRFS、netdev_budgetnetdev_max_backlogtxqueuelen、TCP read/writeバッファが主要な軸である
  • すべてのシステムに通用する単一の設定はなく、リングバッファの増加はドロップを減らせる一方で遅延を増やし、割り込み統合はCPU使用率とHardIRQを減らす代わりに遅延コストを生む可能性がある
  • 高性能パケット処理は PACKET_MMAPDPDKPF_RINGXDP/AF_XDP のような選択肢へ拡張できるが、カーネルバイパス、ゼロコピー、カーネル内高速パスごとにハードウェア依存性、CPU占有、カーネルバージョン要件が異なる

Linux受信経路: NICからソケットまで

  • ネットワークデバイスはパケット到着を知らせるために IRQ を発生させ、LinuxのIRQマッピングは /proc/interrupts に保存される
  • IRQハンドラは非常に高い優先度で実行され、追加のIRQ発生を防ぐ場合があるため、ドライバは長時間かかる作業をIRQコンテキスト外へ先送りする
  • この遅延処理には softIRQ が使われ、ネットワーク受信処理ではCPUごとに ksoftirqd/<cpu-number> カーネルスレッド、softnet_datapoll_list が作られる
  • net_dev_initNET_RX_SOFTIRQ をsoftIRQシステムに登録し、そのハンドラは net_rx_action である
  • パケット到着とNAPI処理

    • NICはネットワークから受け取ったデータを DMA でRAM上のリングバッファに記録する
    • 一部のNICは複数のリングバッファを持つ multiqueue NICである
    • NICがHardIRQを発生させると、ドライバのIRQハンドラが実行される
    • ドライバはNICのIRQをクリアし、napi_schedule を呼び出してNAPI softIRQ pollループを開始する
    • napi_schedule はドライバのNAPI poll構造体を現在のCPUの poll_list に追加し、softIRQ pending bitを設定する
    • ksoftirqd__do_softirq を呼び出すと、pending状態の NET_RX_SOFTIRQ のハンドラ net_rx_action が実行される
  • GROとプロトコルスタックへの進入

    • net_rx_action はNAPI poll listを確認し、budget と経過時間を検査してsoftIRQがCPUを独占しないようにする
    • ドライバの poll 関数はRAM上のリングバッファからパケットを回収する
    • パケットは napi_gro_receive に渡される
    • GRO(Generic Receive Offloading) は小さなパケットを大きなパケットへ再構成し、アプリケーションが処理すべきパケット数を減らすソフトウェアベースのオフロード技術である
    • GROがパケットを保留しない場合、netif_receive_skb を通じてプロトコルスタック上位へ進む
  • RPS有効化の有無による分岐

    • RPS が無効な場合:
      • netif_receive_skb がデータを __netif_receive_core に渡す
      • __netif_receive_core はtapと登録済みプロトコル層ハンドラへデータを渡す
    • RPS が有効な場合:
      • netif_receive_skb がデータを enqueue_to_backlog に渡す
      • パケットはCPUごとのinput queueに入る
      • リモートCPUのNAPI構造体がそのCPUの poll_list に追加され、IPIがキューイングされてリモートCPUのsoftIRQスレッドを起こす
      • リモートCPUの ksoftirqdprocess_backlog poll関数でCPU input queueからパケットを回収する
  • IP、TCP、ソケット受信バッファ

    • パケットはIPv4層で ip_rcv により受信され、netfilterとルーティング最適化を経る
    • 現在のシステム宛てのデータはUDPやTCPのような上位プロトコル層へ渡される
    • TCP受信経路では、tcp_v4_rcv、TCP finite state machine、ソケット探索を経て受信バッファに入る
    • 受信バッファサイズは tcp_rmem のルールに従う
    • tcp_moderate_rcvbuf が有効なら、カーネルが受信バッファを自動調整する
    • tcp_rmem はTCPソケット受信バッファの最小値、デフォルト値、最大値を含む
    • SO_RCVBUF を使うと、そのソケットの受信バッファ自動調整は無効化される
    • net.core.rmem_max はTCP受信バッファサイズの上限であり、より大きなウィンドウはACK送信前により多くのデータを送れるため、遅延を減らしスループットを高められる

Linux送信経路: アプリケーションからNICまで

  • 送信経路は受信より単純だが、qdisc、TCP write buffer、DMA、IRQが関与する
  • アプリケーションが sendmsg のような呼び出しでメッセージを送ると、TCP送信経路が skb_buff を割り当てる
  • パケットは tcp_wmem サイズのソケットwrite bufferに入る
    • tcp_wmem はTCPソケット送信バッファの最小値、デフォルト値、最大値を含む
    • カーネルはTCP送信バッファサイズを最小値と最大値の間で動的に調整する
    • SO_SNDBUF を使うと、そのソケットの送信バッファ自動調整は無効化される
    • net.core.wmem_max はTCP送信バッファサイズの上限である
  • TCPヘッダとIPヘッダが作られ、LOCAL_OUT、ルーティング、POST_ROUTING、fragmentationを経た後、dev_queue_xmit でL2送信関数が呼び出される
  • 出力qdiscは txqueuelen の長さと default_qdisc アルゴリズムを使用する
  • ドライバはパケットをTXリングバッファに入れ、tx-usecs timeout または tx-frames の後に NET_TX_SOFTIRQ を実行する
  • NICはDMAでRAMからパケットを取得して送信し、送信完了後にHardIRQを発生させる
  • ドライバはこのIRQを処理し、NAPI pollシステムを予約してRAMを解放する

観測ツールと基本的な確認ポイント

  • /proc/net/softnet_stat

    • /proc/net/softnet_stat の各行は1つの CPU コアを表し、CPU0 から始まる
    • 各カラムの統計は 16進数 で提供される
    • 1番目のカラムは割り込みハンドラが受信したフレーム数である
    • 2番目のカラムは netdev_max_backlog 超過によりドロップされたフレーム数である
    • 3番目のカラムは処理すべき作業が残っているにもかかわらず、ksoftirqdnetdev_budget または CPU 時間を使い切った回数である
    • 残りのカラムは Linux のバージョンによって異なる場合がある
  • /proc/net/sockstatss

    • /proc/net/sockstat では mem フィールドを確認する
    • この値はすべてのソケットの sk_buff->truesize を合算して計算される
    • ss はソケット統計をダンプするツールで、netstat と似た情報に加え、より多くの TCP および状態情報を表示できる
    • ss -tm は TCP ソケットのメモリ使用量確認に使う
    • rmem_alloc: 受信パケットに割り当てられたメモリ
    • rcv_buf: 受信パケットに割り当て可能な総メモリ
    • wmem_alloc: レイヤー 3 にすでに渡された送信パケットに使われたメモリ
    • snd_buf: 送信パケットに割り当て可能な総メモリ
    • wmem_queued: まだレイヤー 3 に渡されていない送信パケットに割り当てられたメモリ
    • sock_drop: ソケットへ demultiplex される前にドロップされたパケット数
  • netstatsysctl

    • netstat は開いているネットワーク接続とプロトコルスタック統計を出力するコマンドラインツールであり、/proc/net/ ファイルシステムから情報を取得する
    • /proc/net/dev: デバイス情報
    • /proc/net/tcp: TCP ソケット情報
    • /proc/net/unix: Unix domain socket 情報
    • sysctl/proc ファイルシステムに直接値を書き込む代わりに、システム・ネットワーク設定を変更するコマンドである
    • sysctl -w variable=value は一時的な変更に使い、永続的な変更は /etc/sysctl.conf を修正した後、sysctl -p で適用する

NIC リングバッファと割り込み調整

  • NIC リングバッファ

    • RX リングバッファは RAM 上にある固定サイズの FIFO 循環バッファ である
    • リングバッファ自体はパケットデータを保持せず、DMA により RAM に入った skb を指す descriptor を保持する
    • ドロップや overrun が見られる場合はキューサイズを増やせるが、副作用として遅延が増える可能性がある
    • 多くの場合、受信バッファサイズを増やすだけでパケットドロップを防げ、カーネルがバッファを空にする時間をもう少し確保できる
    • 確認と変更は ethtool で行う
    • ethtool -g eth3: 現在の RX/TX リングサイズと最大値を確認
    • ethtool -G eth3 rx 8192 tx 8192: RX/TX バッファを最大値まで増加
    • ethtool -S eth3err, drop, over, miss, timeout, reset, collis などのカウンタで監視する
  • ハードウェア割り込みコアレッシング

    • NIC は rx-usecs timeout または rx-frames 条件まで RX リングバッファにパケット reference を蓄積した後に HardIRQ を発生させることがあり、これを Interrupt coalescence と呼ぶ
    • 早すぎる頻度で割り込むと、カーネルが実行中の作業を頻繁に中断するためシステム性能が悪化する
    • 遅すぎる頻度で割り込むと、NIC からトラフィックを十分な速さで吐き出せず、上書きやトラフィック損失が発生する可能性がある
    • 割り込みコアレッシングの調整は CPU 使用量と HardIRQ を減らし、スループットを高められるが、遅延コストが発生する場合がある
    • ethtool -c eth3 で coalesce パラメータを確認し、ethtool -C eth3 adaptive-rx off rx-usecs 0 rx-frames 0 のように変更できる
    • adaptive mode では、カードがトラフィックパターンとカーネルの受信パターンを見て coalescing 設定を動的に推定する

IRQ affinity と CPU 間の負荷分散

  • IRQ affinity

    • IRQ には、その IRQ の ISR を実行できる CPU コアを定義する smp_affinity 属性がある
    • 割り込み affinity とアプリケーションスレッド affinity を特定の CPU コアに合わせると、キャッシュライン共有によりアプリケーション性能が向上することがある
    • デフォルトでは irqbalance デーモンが制御する
    • 手動調整の前には irqbalance を停止する必要がある
    • /proc/irq/<IRQ_NUMBER>/smp_affinity には CPU コアを表す 16進数のビットマスクが保存される
    • 4 コアサーバーでのデフォルト値 f は、すべての CPU で IRQ を処理できることを意味する
    • echo 1 > /proc/irq/32/smp_affinity は CPU0 のみを使うようにする
    • 32 コアを超えるシステムでは、comma で 32-bit group を区切る
    • IRQ affinity は非常に限定的な構成と事前定義されたワークロードでのみ性能を高められ、諸刃の剣 になり得る
  • RSS

    • 高速な NIC で単一キューと単一 CPU だけでパケットを受信すると、1 つのコアがデータ処理の責任をすべて負い、ほかのコアがアイドル状態になることがある
    • RSS(Receive-side scaling) は、NIC が複数の送受信キューにトラフィックを分散するための NIC 技術である
    • NIC は source/destination IP と TCP/UDP source/destination port に基づいてハッシュを計算し、同じ flow のパケットを単一キューに割り当てつつ、flow を各キューへ均等に分散する
    • RSS はマルチプロセッシング環境で並列受信処理の利点を提供する
    • Linux kernel のドキュメントによれば、RSS は遅延が重要であるか、受信割り込み処理がボトルネックである場合に有効化すべきであり、低遅延ネットワーキングではシステムの CPU 数だけキューを割り当てる設定が最適である
  • RPS, RFS, aRFS

    • RPS(Receive Packet Steering) は RSS のソフトウェア実装に近い
    • RSS がハードウェア割り込みハンドラを実行するキューと CPU を選ぶのに対し、RPS は割り込みハンドラの上位でプロトコル処理を実行する CPU を選ぶ
    • CONFIG_RPS が必要で、SMP ではデフォルトで有効化されている
    • 設定は /sys/class/net/<dev>/queues/rx-<n>/rps_cpus の CPU bitmap で行う
    • RSS があれば不要な場合もあるが、CPU 数がキュー数より多い場合には有用なことがある
    • RFS(Receive Flow Steering) は RPS をアプリケーション locality まで拡張したものだ
    • RPS は flow ベースでパケットを分散するが、ユーザー空間アプリケーションがどの CPU で実行されているかは考慮しない
    • RFS は global flow-to-CPU table である rps_sock_flow_table を維持する
    • net.core.rps_sock_flow_entries でテーブルサイズを調整できる
    • per-queue rps_dev_flow_table は、スケジューラがアプリケーションを新しい CPU に移した際に、残っているパケットのせいで順序が乱れる問題を減らすために使われる
    • aRFS(Accelerated RFS) は RFS 向けのハードウェアアクセラレーション負荷分散メカニズムである
    • パケットをデータを消費するスレッドに近い CPU に直接送るため、RFS より高い性能を出せる可能性がある
    • NIC の ndo_rx_flow_steerntuple filtering、CONFIG_RFS_ACCEL が必要である
    • CPU とキューのマッピングは各受信キューの IRQ affinity から自動的に導出されるため、追加設定は不要である

softIRQ、qdisc、TCPバッファのチューニング

  • softIRQ の予算

    • NAPI polling ルーチンは netdev_budget_usecsnetdev_budgetdev_weight によって制限され、softIRQ が CPU を占有しないようにしている
    • net.core.netdev_budget のデフォルト値は 300 で、softIRQ プロセスが CPU から降りる前に NIC から 300 個のメッセージを空にすることを意味する
    • net.core.netdev_budget_usecs は 1 回の NAPI polling cycle の最大マイクロ秒数である
    • net.core.dev_weight は NAPI interrupt において、カーネルが処理できる CPU ごとの最大パケット数である
    • /proc/net/softnet_stat で 1 列目以外の列が増加している場合、budget の変更が必要な可能性があり、小さな増加は正常なこともある
  • ingress qdisc と netdev_max_backlog

    • netdev_max_backlog は、NIC で受信された後、IP/TCP のようなプロトコルスタックで処理される前のトラフィックが保存されるカーネル内部キューである
    • CPU コアごとに 1 つの backlog queue がある
    • インターフェースがカーネルが処理できる速度よりも速くパケットを受信すると、INPUT 側キューが netdev_max_backlog まで埋まり、超過するとドロップされる
    • デフォルト値は 1000 で、複数の 1Gbps インターフェースや単一の 10Gbps インターフェースでは不足する場合がある
    • /proc/net/softnet_stat の 2 列目は、backlog queue overflow によって増加するカウンタである
    • 値の変更は sysctl -w net.core.netdev_max_backlog <value> で行う
  • egress qdisc、txqueuelendefault_qdisc

    • txqueuelen は、ネットワークインターフェースデバイスのカーネル transmit queue に許可されるパケット数を設定する
    • デフォルト値は、インターフェースドライバによっては 1000 の場合がある
    • ifconfig <interface> txqueuelen value で変更し、ip -s link で RX/TX dropped を確認する
    • default_qdisc は、ネットワークデバイスに使用するデフォルトの queuing discipline である
    • pfifo_fast の代わりに sfqcodelfq_codel のような代替を指定できる
    • tc -s qdisc ls dev <interface> で dropped、overlimits、requeues のような指標を確認する
  • TCP read/write buffer と接続キュー

    • tcp_rmemtcp_wmem は、それぞれ TCP 受信・送信バッファの最小値、デフォルト値、最大値を定義する
    • 変更は次のように行う
      • sysctl -w net.ipv4.tcp_rmem="min default max"
      • sysctl -w net.ipv4.tcp_wmem="min default max"
    • /proc/net/sockstat でバッファ使用状況を確認する
    • Accept queue と SYN queue は net.core.somaxconnnet.ipv4.tcp_max_syn_backlog の影響を受ける
    • net.core.somaxconnlisten() の backlog パラメータの上限であり、この値を変更する場合はアプリケーション側も互換性のある値に変更する必要がある
    • net.ipv4.tcp_syncookies は、SYN flood 攻撃の防御に有用な SYN cookie を有効または無効にする
    • net.ipv4.tcp_congestion_control は、新しい接続に使用する congestion control アルゴリズムを設定する

NUMA とネットワーク性能

  • NUMA(Non-uniform memory access) は、プロセッサが non-local memory よりも local memory により高速にアクセスできるメモリアーキテクチャである
  • ネットワーク処理では CPU がリングバッファメモリにアクセスする必要があるため、NUMA locality はネットワーク性能に影響する可能性がある
  • NUMA は CPU、メモリ、デバイスを複数の node に分割し、高速 interconnect と共通 OS を備えた複数の小さなコンピュータのように動作する
  • NUMA システムでは、デバイスが属する単一 node の CPU コアにそのデバイスの割り込みを集めることがチューニング目標となる
  • ただし NUMA システムはリアルタイムアプリケーションと相性が悪く、予期しないイベント遅延を引き起こすことがある
  • NUMA node は /sys/devices/system/node/node* で確認する
  • デバイス locality は /sys/class/net/<interface>/device/numa_node で確認する
    • -1 は、ハードウェアプラットフォームが実際には NUMA でないか、カーネルが NUMA をエミュレートしている場合、またはデバイスに NUMA locality がない場合を意味する
  • Linux kernel は 2.5 から NUMA をサポートしており、RedHat 系および Debian 系ディストリビューションは numactlnumad を提供している
  • numad は、システム topology とリソース使用量を監視し、十分に大きなメモリおよび CPU 負荷を持つプロセスを効率的な NUMA locality に配置しようとする

より高速なパケット処理の選択肢

  • AF_PACKET v4 と PACKET_MMAP

    • AF_PACKET v4 は Linux の高速なパケットインターフェースで、データパスから system call をなくし、基本的に copy-mode を使用する
    • PACKET_ZEROCOPY を使うと、DMA packet buffer をユーザー空間にマッピングする true zero-copy モードを利用できる
    • 一般的な file read 後の socket send 経路では、user mode と kernel mode の間の context switch と複数回のデータ copy が必要になる
    • zero-copy は重複したデータ copy を排除して性能を高める
    • PACKET_MMAP は高速な packet sniffing のための Linux API である
    • ユーザー空間とカーネルが共有する mmapped ring buffer を提供する
    • 送受信パケットにおいて system call とユーザー空間・カーネル間の copy を減らす
  • DPDK

    • DPDK(Data Plane Development Kit) は、高速なパケット処理のためのユーザー空間ライブラリとドライバーフレームワークである
    • 目的は、NIC とユーザーアプリケーションの間でネットワークパケットを native speed でやり取りすることである
    • 10Gb または 40Gb NIC を対象としており、速度が最も重要な基準である
    • ネットワークスタックではなく、パケット forwarding に焦点を当てる
    • DPDK が NIC を制御すると、すべてのトラフィックはカーネルを迂回し、その NIC はカーネルから見えなくなる
    • ポートは Linux カーネルドライバーから unbind され、vfio_pciigb_uiouio_pci_generic のようなドライバーで管理される
    • その後、アプリケーションと NIC の通信は DPDK PMD が担当する
    • DPDK では大きなメモリ chunk を割り当てるために hugepages の設定が必要である
    • 主な構成要素:
      • EAL: 環境差異を隠蔽する generic interface
      • librte_ring: lockless multi-producer, multi-consumer FIFO API
      • librte_mempool: メモリオブジェクト pool の割り当て
      • librte_mbuf: ネットワークパケットを格納する buffer の生成・操作
      • librte_timer: 非同期関数実行のための timer service
      • PMD: interrupt の代わりに CPU が NIC を継続的に poll するドライバー
    • 制約:
      • ハードウェア依存性が大きい
      • PMD 実行のために CPU core を専用に割り当てる必要があり、100% CPU を使用する
  • PF_RING

    • PF_RING は、高速にパケットを処理し、パケット処理アプリケーションに一貫した API を提供する Linux kernel module と user-space framework である
    • PF_RING は Linux NAPI により NIC からパケットを poll する
    • NAPI が NIC から PF_RING circular buffer へパケットをコピーし、ユーザー空間アプリケーションが ring からパケットを読み取る
    • この構造にはアプリケーションと NAPI という 2 つの poller があり、polling に CPU cycle が使われる
    • 利点は、incoming packet を複数の ring に同時に分散できる点である
    • モジュール型の構造により、ZC module、FPGA-based card module、Stack module、Timeline module、Sysdig module などの追加コンポーネントを利用できる
    • PF_RING はパケット capture と userland forwarding のコストを削減したが、カーネルが NIC から ring にコピーし、userland が ring から読み取って処理する 2 アクター構造のため、最適性能には限界がある
    • PF_RING は 7.5 から AF_XDP adapter のサポートを含む
  • XDP と AF_XDP

    • XDP(eXpress Data Path) は、Linux ネットワークデータパスでパケットを早い段階で横取りする eBPF 実装である
    • XDP は SKB 割り当て前、device driver の RX function 内部で RX packet page を直接処理する
    • eBPF はカーネルで実行されるユーザー定義の sandboxed bytecode である
    • 64-bit register 11 個と 512-byte stack を使用する
    • LLVM backend により、C、Lua、Go、P4、Rust などから eBPF へコンパイルできる
    • in-kernel verifier と JIT compiler を提供し、map、tail call、helper などの機能をサポートする
    • XDP の利用例:
      • DoS 緩和のための pre-stack filtering
      • forwarding と load balancing
      • GRO のような batching 手法
      • flow sampling と monitoring
      • ULP processing
    • XDP は kernel bypass ではなく、カーネルスタック内の fast path であり、TCP/IP stack を置き換えるものではない
    • 専用ハードウェアは不要だが、multi-queue NIC、TX/RX checksum offload、RSS、TSO などの要件がある
    • DPDK と比べた XDP の利点:
      • busy polling または interrupt driven networking を選択できる
      • huge pages が不要
      • 特殊なハードウェア要件がない
      • 専用 CPU は必須ではない
      • 3rd party userspace application からカーネルへパケットを再注入する必要がない
      • ネットワークハードウェアアクセスのための新たな security model が不要
      • 3rd party code/licensing が不要
    • AF_XDP は Linux 4.18 で導入された新しい socket タイプである
    • カーネルを完全に迂回せず、カーネル機能を活用して DPDK や AF_PACKET と似た構造を作れる
    • XDP program が eBPF によって frame をユーザー空間 memory buffer へ redirect できる
    • DMA transfer はユーザー空間メモリを使って zero-copy をサポートする
    • AF_PACKET と比べて 3〜20 倍の性能向上を達成できる
    • 制約:
      • 比較的新しいプロジェクトである
      • 完全なサポートには Linux kernel 5.4 以上が必要である

1件のコメント

 
GN⁺ 2024-07-29
Hacker Newsのコメント
  • 数週間前に読めていたら本当に役立ったはずの資料。
    データセンター間でL2リンク暗号化を行うため、複数ベンダーからハードウェアアプライアンスの見積もりを取ったが、高すぎると感じたので自作してみた。
    汎用ハードウェアで、WireGuardオーバーレイネットワーク上にイーサネットフレームを載せて10Gbps出せるよう構成し、10日ほどの作業の末、最安の提案より約70%、最高額の提案より約95%安く実装できたが、細かいドキュメントの読み込みと多くの実験が必要だった。
    この記事の内容で自分の理解が正しいか検証してみたいし、ざっと見ただけでも有望で包括的に思える。

    • どんな用途でL3トンネルでは不十分だったのか気になる。
    • コードを共有できるならぜひ見たい。どう実装したのかとても気になる。
  • 調整可能な値がこれほど多いなら、自動チューニングソフトウェアを作る価値があるのではと思う。
    ホワイトリストにあるパラメータをランダムに選び、許容範囲内で少し上げ下げして、しばらく性能を測定し、悪化したら戻し、改善したらさらに調整する、という勾配降下法に近いアプローチができそう。

  • 興味深いが、ソフトウェアエンジニアとしては記事に出てくるコマンドを実際に実行する機会はほとんどない。
    システムの大半は何らかのLinuxの縮小版コンテナで動いており、本番システムにはシェルアクセス権がなく、開発やQA環境は負荷などの面で本番と違いすぎるため、バグ再現もたいていあまり役に立たない。
    結局、記事のコマンドを試せるのは個人のシステムを触るときくらいで、プラットフォームエンジニアとして働いているなら有用そう。

    • 低レベル機能の大半は、どうせ動かないか役に立たない可能性が高い。コンテナのネットワークインターフェース実装では、通常vethペアを扱うことになり、ユーザー空間であれこれ奇妙な処理をしているからだ。
      Kubernetesであまり気に入っていない点の一つがネットワーキングモデル。ネットワークカードが1枚しかないと想定し、アプリケーションはその下の層について知る必要がないほど単純だと前提している。
      ネットワーキングモデル全体は、単純化と改善のために2020年代らしく大きく見直す余地がありそうだ。
    • 本番にできるだけ近いステージング環境があるなら、アクセス権のある本番類似環境で実験や分析ができるので、状況によっては役立つかもしれない。
  • net.core.wmem_max はTCP送信バッファサイズの上限とされていて、net.ipv4.tcp_wmem もあるので、2つ気になることがある。

    1. なぜIPv6に対応する値がないのか、2. net.core.wmem_max と何が違うのか知りたい。
    • net.core.wmem_max は名前の通り最大値
      net.ipv4.tcp_wmem は最小、デフォルト、最大の3つの値を持つトリプル値で、ここで指定する最大値は前者の net.core.wmem_max を超えられない。
      TCPはIPv4上で運ばれてもIPv6上で運ばれても同じであるべきプロトコル。
      例: https://docs.redhat.com/en/documentation/red_hat_data_grid/7...
  • ここで少し欠けているのは、100Gbps超のスループットに対するデバッグとチューニング。
    その規模でHTTPを提供すると、最初のボトルネックはたいていメモリ帯域幅で、kTLSが必要になることが多い。
    AMD μProfのようなツールはデバッグに非常に有用で、カーネル空間とユーザー空間で正確に何が起きているかを理解するには、eBPFベースの継続的プロファイリングも役立つ。

  • かなり良さそう。これまでの自分のキャリアでは、性能が必要になるたびに、たいていカーネルバイパスから始めていた。