1
0
mirror of https://github.com/facebookincubator/mvfst.git synced 2025-08-05 11:21:09 +03:00

Use F14FastMap as the retranmission buffer.

Summary:
The retransmission buffer tracks stream frame data we have sent that is currently unacked. We keep this as a sorted `deque`. This isn't so bad for performance, but we can do better if we break ourselves of the requirement that it be sorted (removing a binary search on ACK).

To do this we make the buffer a map of offset -> `StreamBuffer`.

There were two places that were dependent on the sorted nature of the list.

1. For partial reliablity we call `shrinkBuffers` to remove all unacked buffers less than an offset. For this we now have to do it with a full traversal of the retransmission buffer instead of only having to do an O(offset) search. In the future we could make this better by only lazily deleting from the retransmission buffer on ACK or packet loss.

2. We used the start of the retransmission buffer to determine if a delivery callback could be fired for a given offset. We need some new state to track this. Instead of tracking unacked buffers, we now track acked ranges using the existing `IntervalSet`. This set should be small for the typical case, as we think most ACKs will come in order and just cause existing ranges to merge.

Reviewed By: yangchi

Differential Revision: D18609467

fbshipit-source-id: 13cd2164352f1183362be9f675c1bdc686426698
This commit is contained in:
Matt Joras
2019-11-26 09:54:44 -08:00
committed by Facebook Github Bot
parent 7e4bcf30cf
commit b6e134fdee
16 changed files with 253 additions and 166 deletions

View File

@@ -224,7 +224,7 @@ TEST_F(QuicTransportFunctionsTest, TestUpdateConnection) {
EXPECT_TRUE(conn->outstandingPackets.back().isAppLimited);
EXPECT_EQ(stream1->retransmissionBuffer.size(), 1);
auto& rt1 = stream1->retransmissionBuffer.front();
auto& rt1 = stream1->retransmissionBuffer.at(0);
EXPECT_EQ(stream1->currentWriteOffset, 5);
EXPECT_EQ(stream2->currentWriteOffset, 13);
@@ -234,7 +234,7 @@ TEST_F(QuicTransportFunctionsTest, TestUpdateConnection) {
EXPECT_TRUE(eq(*IOBuf::copyBuffer("hey w"), *rt1.data.front()));
EXPECT_EQ(stream2->retransmissionBuffer.size(), 1);
auto& rt2 = stream2->retransmissionBuffer.front();
auto& rt2 = stream2->retransmissionBuffer.at(0);
EXPECT_EQ(rt2.offset, 0);
EXPECT_TRUE(eq(*buf, *rt2.data.front()));
@@ -244,9 +244,9 @@ TEST_F(QuicTransportFunctionsTest, TestUpdateConnection) {
// Testing retransmission
stream1->lossBuffer.push_back(std::move(rt1));
stream1->retransmissionBuffer.pop_front();
stream1->retransmissionBuffer.clear();
stream2->lossBuffer.push_back(std::move(rt2));
stream2->retransmissionBuffer.pop_front();
stream2->retransmissionBuffer.clear();
conn->streamManager->addLoss(stream1->id);
conn->streamManager->addLoss(stream2->id);
@@ -285,17 +285,17 @@ TEST_F(QuicTransportFunctionsTest, TestUpdateConnection) {
EXPECT_EQ(stream1->lossBuffer.size(), 0);
EXPECT_EQ(stream1->retransmissionBuffer.size(), 2);
auto& rt3 = stream1->retransmissionBuffer.back();
auto& rt3 = stream1->retransmissionBuffer.at(5);
EXPECT_TRUE(eq(IOBuf::copyBuffer("hats up"), rt3.data.move()));
auto& rt4 = stream1->retransmissionBuffer.front();
auto& rt4 = stream1->retransmissionBuffer.at(0);
EXPECT_TRUE(eq(*IOBuf::copyBuffer("hey w"), *rt4.data.front()));
// loss buffer should be split into 2. Part in retransmission buffer and
// part remains in loss buffer.
EXPECT_EQ(stream2->lossBuffer.size(), 1);
EXPECT_EQ(stream2->retransmissionBuffer.size(), 1);
auto& rt5 = stream2->retransmissionBuffer.front();
auto& rt5 = stream2->retransmissionBuffer.at(0);
EXPECT_TRUE(eq(*IOBuf::copyBuffer("hey wh"), *rt5.data.front()));
EXPECT_EQ(rt5.offset, 0);
EXPECT_EQ(rt5.eof, 0);
@@ -434,7 +434,7 @@ TEST_F(QuicTransportFunctionsTest, TestUpdateConnectionFinOnly) {
EXPECT_TRUE(frame->fin);
EXPECT_EQ(stream1->retransmissionBuffer.size(), 1);
auto& rt1 = stream1->retransmissionBuffer.front();
auto& rt1 = stream1->retransmissionBuffer.at(0);
EXPECT_EQ(stream1->currentWriteOffset, 1);
EXPECT_EQ(rt1.offset, 0);
@@ -481,7 +481,7 @@ TEST_F(QuicTransportFunctionsTest, TestUpdateConnectionAllBytesExceptFin) {
EXPECT_EQ(stream1->currentWriteOffset, buf->computeChainDataLength());
EXPECT_EQ(stream1->retransmissionBuffer.size(), 1);
auto& rt1 = stream1->retransmissionBuffer.front();
auto& rt1 = stream1->retransmissionBuffer.at(0);
EXPECT_EQ(rt1.offset, 0);
EXPECT_EQ(
rt1.data.front()->computeChainDataLength(),
@@ -1217,9 +1217,6 @@ TEST_F(QuicTransportFunctionsTest, WriteQuicDataToSocketRetxBufferSorted) {
getVersion(*conn),
conn->transportSettings.writeConnectionDataPacketsLimit);
EXPECT_EQ(2, stream->retransmissionBuffer.size());
EXPECT_GT(
stream->retransmissionBuffer.back().offset,
stream->retransmissionBuffer.front().offset);
}
TEST_F(QuicTransportFunctionsTest, NothingWritten) {