1
0
mirror of https://github.com/facebook/proxygen.git synced 2026-10-24 01:33:54 +03:00

Requeue a split body event without recounting its chain

Summary:
Avoid rebuilding a `BufQueue` and walks the whole chain to count its bytes again. Calling the `.move()`

 Old code:
  1. `bodyBuf.move()` hands back a bare unique_ptr<IOBuf> and the calculated `chainLength_` is recalculated walking the chain again (this is unnecessary)

New code:
  1. std::move copies nothing on its own. It only marks bodyBuf as an rvalue BufQueue which then use the move constructor

Cowboy edge task T289680342: this walk is ≈ 96 % of the measured cost (≈ $60 K a year on edge hosts).

Reviewed By: hanidamlaj

Differential Revision: D122754751

fbshipit-source-id: fe5ee78f318332de6f1b842c786e8c30e4b80c3e
This commit is contained in:
Will Wang
2026-10-03 05:49:21 -07:00
committed by meta-codesync[bot]
parent aafaa19469
commit bc95264c43
2 changed files with 23 additions and 1 deletions

View File

@@ -267,7 +267,7 @@ folly::coro::Task<HTTPBodyEvent> HTTPStreamSource::readBodyEvent(uint32_t max) {
// the queue. If this happens, EOM must be false.
BufQueue bodyBuf(std::move(res.event.body));
res.event.body = bodyBuf.splitAtMost(max);
bodyQueue_.emplace_front(bodyBuf.move(), res.eom);
bodyQueue_.emplace_front(std::move(bodyBuf), res.eom);
res.eom = false;
length = max;
}

View File

@@ -224,6 +224,28 @@ TEST_F(HTTPStreamSourceTest, Body) {
EXPECT_EQ(bodyEvents_[4].eom, true);
}
// A body event larger than the read limit is split, and the rest goes back to
// the front of the queue with its length.
TEST_F(HTTPStreamSourceTest, SplitBodyKeepsTheRemainderLength) {
auto resp = std::make_unique<HTTPMessage>();
resp->setStatusCode(200);
stream_.headers(std::move(resp));
stream_.body(BufQueue(folly::IOBuf::copyBuffer("abcdef")), 0);
stream_.eom();
co_withExecutor(&evb_, drainSource(&stream_, 4)).start();
evb_.loopOnce();
EXPECT_FALSE(error_.hasValue());
ASSERT_GE(bodyEvents_.size(), 2);
EXPECT_EQ(bodyEvents_[0].event.body.chainLength(), 4);
EXPECT_FALSE(bodyEvents_[0].eom);
EXPECT_EQ(bodyEvents_[1].event.body.chainLength(), 2);
auto rest = bodyEvents_[1].event.body.move();
rest->coalesce();
EXPECT_EQ(rest->moveToFbString(), std::string("ef"));
}
TEST_F(HTTPStreamSourceTest, PushPromiseBeforeResponseHeaders) {
auto promiseSource = HTTPFixedSource::makeFixedResponse(
200, folly::IOBuf::copyBuffer("push body"));