From 3806c95073f2453944dd8fbcb6a3a11f5f6c15d1 Mon Sep 17 00:00:00 2001 From: skywind3000 Date: Fri, 3 Jun 2016 20:28:21 +0800 Subject: [PATCH] improve performance & optimize fast-ack --- ikcp.c | 45 ++++++++++++++++++++++++++++++++++++++------- test.cpp | 12 +++++++----- test.h | 8 ++++++++ 3 files changed, 53 insertions(+), 12 deletions(-) diff --git a/ikcp.c b/ikcp.c index 1335ddf..2824cd8 100644 --- a/ikcp.c +++ b/ikcp.c @@ -541,15 +541,14 @@ static void ikcp_parse_ack(ikcpcb *kcp, IUINT32 sn) kcp->nsnd_buf--; break; } - else { - seg->fastack++; + if (_itimediff(sn, seg->sn) < 0) { + break; } } } static void ikcp_parse_una(ikcpcb *kcp, IUINT32 una) { -#if 1 struct IQUEUEHEAD *p, *next; for (p = kcp->snd_buf.next; p != &kcp->snd_buf; p = next) { IKCPSEG *seg = iqueue_entry(p, IKCPSEG, node); @@ -562,7 +561,25 @@ static void ikcp_parse_una(ikcpcb *kcp, IUINT32 una) break; } } -#endif +} + +static void ikcp_parse_fastack(ikcpcb *kcp, IUINT32 sn) +{ + struct IQUEUEHEAD *p, *next; + + if (_itimediff(sn, kcp->snd_una) < 0 || _itimediff(sn, kcp->snd_nxt) >= 0) + return; + + for (p = kcp->snd_buf.next; p != &kcp->snd_buf; p = next) { + IKCPSEG *seg = iqueue_entry(p, IKCPSEG, node); + next = p->next; + if (_itimediff(sn, seg->sn) < 0) { + break; + } + else if (sn != seg->sn) { + seg->fastack++; + } + } } @@ -684,6 +701,8 @@ void ikcp_parse_data(ikcpcb *kcp, IKCPSEG *newseg) int ikcp_input(ikcpcb *kcp, const char *data, long size) { IUINT32 una = kcp->snd_una; + IUINT32 maxack = 0; + int flag = 0; if (ikcp_canlog(kcp, IKCP_LOG_INPUT)) { ikcp_log(kcp, IKCP_LOG_INPUT, "[RI] %d bytes", size); @@ -728,6 +747,14 @@ int ikcp_input(ikcpcb *kcp, const char *data, long size) } ikcp_parse_ack(kcp, sn); ikcp_shrink_buf(kcp); + if (flag == 0) { + flag = 1; + maxack = sn; + } else { + if (_itimediff(sn, maxack) > 0) { + maxack = sn; + } + } if (ikcp_canlog(kcp, IKCP_LOG_IN_ACK)) { ikcp_log(kcp, IKCP_LOG_IN_DATA, "input ack: sn=%lu rtt=%ld rto=%ld", sn, @@ -784,6 +811,10 @@ int ikcp_input(ikcpcb *kcp, const char *data, long size) size -= len; } + if (flag != 0) { + ikcp_parse_fastack(kcp, maxack); + } + if (_itimediff(kcp->snd_una, una) > 0) { if (kcp->cwnd < kcp->rmt_wnd) { IUINT32 mss = kcp->mss; @@ -865,7 +896,7 @@ void ikcp_flush(ikcpcb *kcp) count = kcp->ackcount; for (i = 0; i < count; i++) { size = (int)(ptr - buffer); - if (size + IKCP_OVERHEAD > (int)kcp->mtu) { + if (size + (int)IKCP_OVERHEAD > (int)kcp->mtu) { ikcp_output(kcp, buffer, size); ptr = buffer; } @@ -901,7 +932,7 @@ void ikcp_flush(ikcpcb *kcp) if (kcp->probe & IKCP_ASK_SEND) { seg.cmd = IKCP_CMD_WASK; size = (int)(ptr - buffer); - if (size + IKCP_OVERHEAD > (int)kcp->mtu) { + if (size + (int)IKCP_OVERHEAD > (int)kcp->mtu) { ikcp_output(kcp, buffer, size); ptr = buffer; } @@ -912,7 +943,7 @@ void ikcp_flush(ikcpcb *kcp) if (kcp->probe & IKCP_ASK_TELL) { seg.cmd = IKCP_CMD_WINS; size = (int)(ptr - buffer); - if (size + IKCP_OVERHEAD > (int)kcp->mtu) { + if (size + (int)IKCP_OVERHEAD > (int)kcp->mtu) { ikcp_output(kcp, buffer, size); ptr = buffer; } diff --git a/test.cpp b/test.cpp index 4736055..b0fdb98 100644 --- a/test.cpp +++ b/test.cpp @@ -71,6 +71,8 @@ void test(int mode) // 第五个参数 为是否禁用常规流控,这里禁止 ikcp_nodelay(kcp1, 1, 10, 2, 1); ikcp_nodelay(kcp2, 1, 10, 2, 1); + kcp1->rx_minrto = 10; + kcp1->fastresend = 1; } @@ -87,8 +89,8 @@ void test(int mode) // 每隔 20ms,kcp1发送数据 for (; current >= slap; slap += 20) { - *(IUINT32*)(buffer + 0) = index++; - *(IUINT32*)(buffer + 4) = current; + ((IUINT32*)buffer)[0] = index++; + ((IUINT32*)buffer)[1] = current; // 发送上层协议包 ikcp_send(kcp1, buffer, 8); @@ -151,15 +153,15 @@ void test(int mode) const char *names[3] = { "default", "normal", "fast" }; printf("%s mode result (%dms):\n", names[mode], (int)ts1); - printf("avgrtt=%d maxrtt=%d\n", (int)(sumrtt / count), maxrtt); + printf("avgrtt=%d maxrtt=%d tx=%d\n", (int)(sumrtt / count), (int)maxrtt, (int)vnet->tx1); printf("press enter to next ...\n"); char ch; scanf("%c", &ch); } int main() { - test(0); // 默认模式,类似 TCP:正常模式,无快速重传,常规流控 - test(1); // 普通模式,关闭流控等 +//test(0); // 默认模式,类似 TCP:正常模式,无快速重传,常规流控 +//test(1); // 普通模式,关闭流控等 test(2); // 快速模式,所有开关都打开,且关闭流控 return 0; } diff --git a/test.h b/test.h index 7db5f98..1dd4319 100644 --- a/test.h +++ b/test.h @@ -146,6 +146,7 @@ protected: class LatencySimulator { public: + virtual ~LatencySimulator() { clear(); } @@ -160,6 +161,7 @@ public: this->rttmin = rttmin / 2; this->rttmax = rttmax / 2; this->nmax = nmax; + tx1 = tx2 = 0; } // 清除数据 @@ -179,9 +181,11 @@ public: // peer - 端点0/1,从0发送,从1接收;从1发送从0接收 void send(int peer, const void *data, int size) { if (peer == 0) { + tx1++; if (r12.random() < lostrate) return; if ((int)p12.size() >= nmax) return; } else { + tx2++; if (r21.random() < lostrate) return; if ((int)p21.size() >= nmax) return; } @@ -222,6 +226,10 @@ public: return maxsize; } +public: + int tx1; + int tx2; + protected: IUINT32 current; int lostrate;