improve performance & optimize fast-ack

This commit is contained in:
skywind3000 2016-06-03 20:28:21 +08:00
parent aec1aa6ef1
commit 3806c95073
3 changed files with 53 additions and 12 deletions

45
ikcp.c
View File

@ -541,15 +541,14 @@ static void ikcp_parse_ack(ikcpcb *kcp, IUINT32 sn)
kcp->nsnd_buf--; kcp->nsnd_buf--;
break; break;
} }
else { if (_itimediff(sn, seg->sn) < 0) {
seg->fastack++; break;
} }
} }
} }
static void ikcp_parse_una(ikcpcb *kcp, IUINT32 una) static void ikcp_parse_una(ikcpcb *kcp, IUINT32 una)
{ {
#if 1
struct IQUEUEHEAD *p, *next; struct IQUEUEHEAD *p, *next;
for (p = kcp->snd_buf.next; p != &kcp->snd_buf; p = next) { for (p = kcp->snd_buf.next; p != &kcp->snd_buf; p = next) {
IKCPSEG *seg = iqueue_entry(p, IKCPSEG, node); IKCPSEG *seg = iqueue_entry(p, IKCPSEG, node);
@ -562,7 +561,25 @@ static void ikcp_parse_una(ikcpcb *kcp, IUINT32 una)
break; 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) int ikcp_input(ikcpcb *kcp, const char *data, long size)
{ {
IUINT32 una = kcp->snd_una; IUINT32 una = kcp->snd_una;
IUINT32 maxack = 0;
int flag = 0;
if (ikcp_canlog(kcp, IKCP_LOG_INPUT)) { if (ikcp_canlog(kcp, IKCP_LOG_INPUT)) {
ikcp_log(kcp, IKCP_LOG_INPUT, "[RI] %d bytes", size); 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_parse_ack(kcp, sn);
ikcp_shrink_buf(kcp); 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)) { if (ikcp_canlog(kcp, IKCP_LOG_IN_ACK)) {
ikcp_log(kcp, IKCP_LOG_IN_DATA, ikcp_log(kcp, IKCP_LOG_IN_DATA,
"input ack: sn=%lu rtt=%ld rto=%ld", sn, "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; size -= len;
} }
if (flag != 0) {
ikcp_parse_fastack(kcp, maxack);
}
if (_itimediff(kcp->snd_una, una) > 0) { if (_itimediff(kcp->snd_una, una) > 0) {
if (kcp->cwnd < kcp->rmt_wnd) { if (kcp->cwnd < kcp->rmt_wnd) {
IUINT32 mss = kcp->mss; IUINT32 mss = kcp->mss;
@ -865,7 +896,7 @@ void ikcp_flush(ikcpcb *kcp)
count = kcp->ackcount; count = kcp->ackcount;
for (i = 0; i < count; i++) { for (i = 0; i < count; i++) {
size = (int)(ptr - buffer); size = (int)(ptr - buffer);
if (size + IKCP_OVERHEAD > (int)kcp->mtu) { if (size + (int)IKCP_OVERHEAD > (int)kcp->mtu) {
ikcp_output(kcp, buffer, size); ikcp_output(kcp, buffer, size);
ptr = buffer; ptr = buffer;
} }
@ -901,7 +932,7 @@ void ikcp_flush(ikcpcb *kcp)
if (kcp->probe & IKCP_ASK_SEND) { if (kcp->probe & IKCP_ASK_SEND) {
seg.cmd = IKCP_CMD_WASK; seg.cmd = IKCP_CMD_WASK;
size = (int)(ptr - buffer); size = (int)(ptr - buffer);
if (size + IKCP_OVERHEAD > (int)kcp->mtu) { if (size + (int)IKCP_OVERHEAD > (int)kcp->mtu) {
ikcp_output(kcp, buffer, size); ikcp_output(kcp, buffer, size);
ptr = buffer; ptr = buffer;
} }
@ -912,7 +943,7 @@ void ikcp_flush(ikcpcb *kcp)
if (kcp->probe & IKCP_ASK_TELL) { if (kcp->probe & IKCP_ASK_TELL) {
seg.cmd = IKCP_CMD_WINS; seg.cmd = IKCP_CMD_WINS;
size = (int)(ptr - buffer); size = (int)(ptr - buffer);
if (size + IKCP_OVERHEAD > (int)kcp->mtu) { if (size + (int)IKCP_OVERHEAD > (int)kcp->mtu) {
ikcp_output(kcp, buffer, size); ikcp_output(kcp, buffer, size);
ptr = buffer; ptr = buffer;
} }

View File

@ -71,6 +71,8 @@ void test(int mode)
// 第五个参数 为是否禁用常规流控,这里禁止 // 第五个参数 为是否禁用常规流控,这里禁止
ikcp_nodelay(kcp1, 1, 10, 2, 1); ikcp_nodelay(kcp1, 1, 10, 2, 1);
ikcp_nodelay(kcp2, 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)
// 每隔 20mskcp1发送数据 // 每隔 20mskcp1发送数据
for (; current >= slap; slap += 20) { for (; current >= slap; slap += 20) {
*(IUINT32*)(buffer + 0) = index++; ((IUINT32*)buffer)[0] = index++;
*(IUINT32*)(buffer + 4) = current; ((IUINT32*)buffer)[1] = current;
// 发送上层协议包 // 发送上层协议包
ikcp_send(kcp1, buffer, 8); ikcp_send(kcp1, buffer, 8);
@ -151,15 +153,15 @@ void test(int mode)
const char *names[3] = { "default", "normal", "fast" }; const char *names[3] = { "default", "normal", "fast" };
printf("%s mode result (%dms):\n", names[mode], (int)ts1); 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"); printf("press enter to next ...\n");
char ch; scanf("%c", &ch); char ch; scanf("%c", &ch);
} }
int main() int main()
{ {
test(0); // 默认模式,类似 TCP正常模式无快速重传常规流控 //test(0); // 默认模式,类似 TCP正常模式无快速重传常规流控
test(1); // 普通模式,关闭流控等 //test(1); // 普通模式,关闭流控等
test(2); // 快速模式,所有开关都打开,且关闭流控 test(2); // 快速模式,所有开关都打开,且关闭流控
return 0; return 0;
} }

8
test.h
View File

@ -146,6 +146,7 @@ protected:
class LatencySimulator class LatencySimulator
{ {
public: public:
virtual ~LatencySimulator() { virtual ~LatencySimulator() {
clear(); clear();
} }
@ -160,6 +161,7 @@ public:
this->rttmin = rttmin / 2; this->rttmin = rttmin / 2;
this->rttmax = rttmax / 2; this->rttmax = rttmax / 2;
this->nmax = nmax; this->nmax = nmax;
tx1 = tx2 = 0;
} }
// 清除数据 // 清除数据
@ -179,9 +181,11 @@ public:
// peer - 端点0/1从0发送从1接收从1发送从0接收 // peer - 端点0/1从0发送从1接收从1发送从0接收
void send(int peer, const void *data, int size) { void send(int peer, const void *data, int size) {
if (peer == 0) { if (peer == 0) {
tx1++;
if (r12.random() < lostrate) return; if (r12.random() < lostrate) return;
if ((int)p12.size() >= nmax) return; if ((int)p12.size() >= nmax) return;
} else { } else {
tx2++;
if (r21.random() < lostrate) return; if (r21.random() < lostrate) return;
if ((int)p21.size() >= nmax) return; if ((int)p21.size() >= nmax) return;
} }
@ -222,6 +226,10 @@ public:
return maxsize; return maxsize;
} }
public:
int tx1;
int tx2;
protected: protected:
IUINT32 current; IUINT32 current;
int lostrate; int lostrate;