Skip to content

Commit 24e04e1

Browse files
pfarcasanufacebook-github-bot
authored andcommitted
vector-backed set for QuicPriorityQueue
Summary: Perf! Reviewed By: mjoras Differential Revision: D44089470 fbshipit-source-id: 152d7317ff585a54dceb1c1b71167e3be0ca7b73
1 parent d2cb779 commit 24e04e1

File tree

2 files changed

+45
-19
lines changed

2 files changed

+45
-19
lines changed

quic/state/QuicPriorityQueue.h

Lines changed: 42 additions & 18 deletions
Original file line numberDiff line numberDiff line change
@@ -8,6 +8,7 @@
88
#pragma once
99

1010
#include <folly/container/F14Map.h>
11+
#include <folly/sorted_vector_types.h>
1112
#include <glog/logging.h>
1213
#include <set>
1314

@@ -34,6 +35,8 @@ struct Priority {
3435

3536
extern const Priority kDefaultPriority;
3637

38+
using StreamSet = folly::sorted_vector_set<StreamId>;
39+
3740
/**
3841
* Priority queue for Quic streams. It represents each level/incremental bucket
3942
* as an entry in a vector. Each entry holds a set of streams (sorted by
@@ -49,43 +52,59 @@ struct PriorityQueue {
4952
const Level& level;
5053

5154
public:
52-
explicit Iterator(const Level& inLevel)
53-
: level(inLevel), nextStreamIt(level.streams.end()) {}
55+
explicit Iterator(const Level& inLevel) : level(inLevel) {}
5456
virtual ~Iterator() = default;
55-
virtual void begin() const {
56-
CHECK(!level.empty());
57-
if (nextStreamIt == level.streams.end()) {
58-
nextStreamIt = level.streams.begin();
59-
}
60-
}
57+
virtual void begin() const = 0;
6158
virtual bool end() const = 0;
6259
virtual StreamId current() const {
6360
return *nextStreamIt;
6461
}
6562
virtual void next() = 0;
66-
mutable std::set<StreamId>::const_iterator nextStreamIt;
63+
virtual void override(StreamSet::const_iterator it) {
64+
nextStreamIt = it;
65+
}
66+
mutable StreamSet::const_iterator nextStreamIt;
6767
};
6868

6969
class IncrementalIterator : public Iterator {
7070
private:
71-
mutable std::set<StreamId>::const_iterator startStreamIt;
71+
mutable std::optional<StreamId> startStreamId;
72+
mutable std::optional<StreamId> nextStreamId;
7273

7374
public:
74-
explicit IncrementalIterator(const Level& inLevel)
75-
: Iterator(inLevel), startStreamIt(nextStreamIt) {}
75+
explicit IncrementalIterator(const Level& inLevel) : Iterator(inLevel) {}
7676
void begin() const override {
77-
Iterator::begin();
78-
startStreamIt = nextStreamIt;
77+
nextStreamIt = findStart();
78+
nextStreamId = *nextStreamIt;
79+
startStreamId = *nextStreamIt;
7980
}
8081
bool end() const override {
81-
return nextStreamIt == startStreamIt;
82+
return *nextStreamId == *startStreamId;
8283
}
8384
void next() override {
8485
CHECK(!level.empty());
8586
nextStreamIt++;
8687
if (nextStreamIt == level.streams.end()) {
8788
nextStreamIt = level.streams.begin();
8889
}
90+
nextStreamId = *nextStreamIt;
91+
}
92+
void override(StreamSet::const_iterator it) override {
93+
Iterator::override(it);
94+
nextStreamId = *it;
95+
}
96+
97+
private:
98+
StreamSet::const_iterator findStart() const {
99+
CHECK(!level.empty());
100+
if (!nextStreamId) {
101+
return level.streams.begin();
102+
}
103+
auto upperIt = level.streams.lower_bound(*nextStreamId);
104+
if (upperIt == level.streams.end()) {
105+
return level.streams.begin();
106+
}
107+
return upperIt;
89108
}
90109
};
91110

@@ -98,14 +117,13 @@ struct PriorityQueue {
98117
bool end() const override {
99118
return nextStreamIt == level.streams.end();
100119
}
101-
102120
void next() override {
103121
CHECK(!level.empty());
104122
nextStreamIt++;
105123
}
106124
};
107125

108-
std::set<StreamId> streams;
126+
StreamSet streams;
109127
bool incremental{false};
110128
std::unique_ptr<Iterator> iterator;
111129

@@ -194,7 +212,13 @@ struct PriorityQueue {
194212
auto& level = levels[it->second];
195213
auto streamIt = level.streams.find(id);
196214
CHECK(streamIt != level.streams.end());
197-
level.iterator->nextStreamIt = streamIt;
215+
level.iterator->override(streamIt);
216+
}
217+
218+
// Only used for testing
219+
void prepareIterator(Priority pri = kDefaultPriority) {
220+
auto& level = levels[priority2index(pri)];
221+
level.iterator->begin();
198222
}
199223

200224
// Only used for testing

quic/state/test/QuicPriorityQueueTest.cpp

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -25,7 +25,6 @@ TEST_F(QuicPriorityQueueTest, TestBasic) {
2525
// Insert two streams for every level and incremental
2626
for (uint8_t i = 0; i < queue_.levels.size(); i++) {
2727
queue_.insertOrUpdate(id++, Priority(i / 2, i & 0x1));
28-
queue_.setNextScheduledStream(id - 1);
2928
queue_.insertOrUpdate(id++, Priority(i / 2, i & 0x1));
3029
}
3130

@@ -185,6 +184,7 @@ TEST_F(QuicPriorityQueueTest, TestUpdate) {
185184
queue_.insertOrUpdate(0, Priority(0, true));
186185
EXPECT_EQ(queue_.count(0), 1);
187186

187+
queue_.prepareIterator(Priority(0, true));
188188
EXPECT_EQ(queue_.getNextScheduledStream(Priority(0, true)), 0);
189189
}
190190

@@ -193,8 +193,10 @@ TEST_F(QuicPriorityQueueTest, UpdateIfExist) {
193193
EXPECT_EQ(0, queue_.count(0));
194194

195195
queue_.insertOrUpdate(0, Priority(0, false));
196+
queue_.prepareIterator(Priority(0, false));
196197
EXPECT_EQ(queue_.getNextScheduledStream(Priority(0, false)), 0);
197198
queue_.updateIfExist(0, Priority(1, true));
199+
queue_.prepareIterator(Priority(1, true));
198200
EXPECT_EQ(queue_.getNextScheduledStream(Priority(1, true)), 0);
199201
}
200202

0 commit comments

Comments
 (0)