aboutsummaryrefslogtreecommitdiffstats
path: root/net/ipv4/tcp_output.c
diff options
context:
space:
mode:
authorEric Dumazet <edumazet@google.com>2018-10-15 12:37:56 -0400
committerDavid S. Miller <davem@davemloft.net>2018-10-16 01:56:42 -0400
commit864e5c090749448e879e86bec06ee396aa2c19c5 (patch)
tree25eae7e82f14b3b683fc0288a1cd83d3b87a4af2 /net/ipv4/tcp_output.c
parent7baf33bdac37da65ddce3adf4daa8c7805802174 (diff)
tcp: optimize tcp internal pacing
When TCP implements its own pacing (when no fq packet scheduler is used), it is arming high resolution timer after a packet is sent. But in many cases (like TCP_RR kind of workloads), this high resolution timer expires before the application attempts to write the following packet. This overhead also happens when the flow is ACK clocked and cwnd limited instead of being limited by the pacing rate. This leads to extra overhead (high number of IRQ) Now tcp_wstamp_ns is reserved for the pacing timer only (after commit "tcp: do not change tcp_wstamp_ns in tcp_mstamp_refresh"), we can setup the timer only when a packet is about to be sent, and if tcp_wstamp_ns is in the future. This leads to a ~10% performance increase in TCP_RR workloads. Signed-off-by: Eric Dumazet <edumazet@google.com> Signed-off-by: David S. Miller <davem@davemloft.net>
Diffstat (limited to 'net/ipv4/tcp_output.c')
-rw-r--r--net/ipv4/tcp_output.c31
1 files changed, 16 insertions, 15 deletions
diff --git a/net/ipv4/tcp_output.c b/net/ipv4/tcp_output.c
index 5474c9854f25..d212e4cbc689 100644
--- a/net/ipv4/tcp_output.c
+++ b/net/ipv4/tcp_output.c
@@ -975,16 +975,6 @@ enum hrtimer_restart tcp_pace_kick(struct hrtimer *timer)
975 return HRTIMER_NORESTART; 975 return HRTIMER_NORESTART;
976} 976}
977 977
978static void tcp_internal_pacing(struct sock *sk)
979{
980 if (!tcp_needs_internal_pacing(sk))
981 return;
982 hrtimer_start(&tcp_sk(sk)->pacing_timer,
983 ns_to_ktime(tcp_sk(sk)->tcp_wstamp_ns),
984 HRTIMER_MODE_ABS_PINNED_SOFT);
985 sock_hold(sk);
986}
987
988static void tcp_update_skb_after_send(struct sock *sk, struct sk_buff *skb, 978static void tcp_update_skb_after_send(struct sock *sk, struct sk_buff *skb,
989 u64 prior_wstamp) 979 u64 prior_wstamp)
990{ 980{
@@ -1005,8 +995,6 @@ static void tcp_update_skb_after_send(struct sock *sk, struct sk_buff *skb,
1005 /* take into account OS jitter */ 995 /* take into account OS jitter */
1006 len_ns -= min_t(u64, len_ns / 2, credit); 996 len_ns -= min_t(u64, len_ns / 2, credit);
1007 tp->tcp_wstamp_ns += len_ns; 997 tp->tcp_wstamp_ns += len_ns;
1008
1009 tcp_internal_pacing(sk);
1010 } 998 }
1011 } 999 }
1012 list_move_tail(&skb->tcp_tsorted_anchor, &tp->tsorted_sent_queue); 1000 list_move_tail(&skb->tcp_tsorted_anchor, &tp->tsorted_sent_queue);
@@ -2186,10 +2174,23 @@ static int tcp_mtu_probe(struct sock *sk)
2186 return -1; 2174 return -1;
2187} 2175}
2188 2176
2189static bool tcp_pacing_check(const struct sock *sk) 2177static bool tcp_pacing_check(struct sock *sk)
2190{ 2178{
2191 return tcp_needs_internal_pacing(sk) && 2179 struct tcp_sock *tp = tcp_sk(sk);
2192 hrtimer_is_queued(&tcp_sk(sk)->pacing_timer); 2180
2181 if (!tcp_needs_internal_pacing(sk))
2182 return false;
2183
2184 if (tp->tcp_wstamp_ns <= tp->tcp_clock_cache)
2185 return false;
2186
2187 if (!hrtimer_is_queued(&tp->pacing_timer)) {
2188 hrtimer_start(&tp->pacing_timer,
2189 ns_to_ktime(tp->tcp_wstamp_ns),
2190 HRTIMER_MODE_ABS_PINNED_SOFT);
2191 sock_hold(sk);
2192 }
2193 return true;
2193} 2194}
2194 2195
2195/* TCP Small Queues : 2196/* TCP Small Queues :