アプリケーションがwrite/sendmsgシステムコールを実行する際に可能な限りパケットを合体させることでパケット送信の総量を抑えるというもの。
ソース自体はこのあたり。NICやQueueing discipline: qdiscにデータがまだある場合はまだ送らないようにするというコメントが書いてある。
/* If a not yet filled skb is pushed, do not send it if * we have data packets in Qdisc or NIC queues : * Because TX completion will happen shortly, it gives a chance * to coalesce future sendmsg() payload into this skb, without * need for a timer, and with no latency trade off. * As packets containing data payload have a bigger truesize * than pure acks (dataless) packets, the last checks prevent * autocorking if we only have an ACK in Qdisc/NIC queues, * or if TX completion was delayed after we processed ACK packet. */ static bool tcp_should_autocork(struct sock *sk, struct sk_buff *skb, int size_goal) { return skb->len < size_goal && READ_ONCE(sock_net(sk)->ipv4.sysctl_tcp_autocorking) && !tcp_rtx_queue_empty(sk) && refcount_read(&sk->sk_wmem_alloc) > skb->truesize && tcp_skb_can_collapse_to(skb); }
アプリケーションのパフォーマンス
Nginxではtcp_nopushを設定することで切り替えることができる。やってみたがそこまで優位な差は見られなかった。(同一ハードウェア上で2台のVMを使ってabで負荷をかけつつ実施してみた)
上記の記事を見るとtcp_nopush自体が効いているのかまでは不明だったが効果はありそうに見えている。
Linuxのプルリクエストを見るとperf statコマンドを使用したパフォーマンステストでは、自動コーキングを有効にすると9410.39、無効にすると6624.89という結果が得られた。と書いてある。
こちらの検証も参考になりました。
Nagleアルゴリズム
遅延させると言えばNagleアルゴリズムあたりも思い浮かぶ。TCP_CORKは、アプリケーションがデータを効率的に大きな塊にまとめて送信するために明示的に使用するオプションです。一方、Nagleアルゴリズムは、小さなデータ送信のオーバーヘッドを自動的に抑制し、ネットワークの効率を向上させるために使うという理解をした。
Nagleアルゴリズムはtcp_nodelayを設定することで無効化することができる。isuconなんかでnginx.confなんかに以下のように書くことがあるがこの場合はNagleアルゴリズムを無効化してTCP_CORKを有効化しています。
http { # 基本設定 sendfile on; tcp_nopush on; tcp_nodelay on; types_hash_max_size 2048; server_tokens off; }
Nginxのソースは読んでいないのですがそもそもどっちも設定する必要はないとのこと?(要確認)