Skip to content

Commit

Permalink
fix lazy serialization performance in pathological case
Browse files Browse the repository at this point in the history
Summary:
`rewriteDouble()` currently walks the whole output queue, which means
in a pathological case of serializing container of lazy objects we get
accidentally quadratic performance.

Reviewed By: luciang

Differential Revision: D44607256

fbshipit-source-id: 4072a1f76c97d37089aa97b1f419d78a3701a38b
  • Loading branch information
Philip Pronin authored and facebook-github-bot committed Apr 2, 2023
1 parent 4076522 commit b8b3ed5
Showing 1 changed file with 25 additions and 0 deletions.
25 changes: 25 additions & 0 deletions folly/io/Cursor.h
Original file line number Diff line number Diff line change
Expand Up @@ -908,6 +908,23 @@ class RWCursor : public detail::CursorBase<RWCursor<access>, IOBuf>,
explicit RWCursor(IOBufQueue& queue)
: RWCursor((queue.flushCache(), queue.head_.get())) {}

// Efficient way to advance to position cursor to the end of the queue,
// using cached length instead of a walk via advanceToEnd().
struct AtEnd {};
RWCursor(IOBufQueue& queue, AtEnd) : RWCursor(queue) {
if (!queue.options().cacheChainLength) {
this->advanceToEnd();
} else {
this->crtBuf_ = this->buffer_->prev();
this->crtBegin_ = this->crtBuf_->data();
this->crtEnd_ = this->crtBuf_->tail();
this->crtPos_ = this->crtEnd_;
this->absolutePos_ =
queue.chainLength() - (this->crtPos_ - this->crtBegin_);
DCHECK_EQ(this->getCurrentPosition(), queue.chainLength());
}
}

template <class OtherDerived, class OtherBuf>
explicit RWCursor(const detail::CursorBase<OtherDerived, OtherBuf>& cursor)
: detail::CursorBase<RWCursor<access>, IOBuf>(cursor),
Expand Down Expand Up @@ -1260,6 +1277,14 @@ class QueueAppender : public detail::Writable<QueueAppender> {
return RWCursor<access>(*queueCache_.queue());
}

template <CursorAccess access>
RWCursor<access> tail(size_t n) {
RWCursor<access> result(
*queueCache_.queue(), typename RWCursor<access>::AtEnd{});
result -= n;
return result;
}

void trimEnd(size_t n) { queueCache_.queue()->trimEnd(n); }

private:
Expand Down

0 comments on commit b8b3ed5

Please sign in to comment.