Skip to content

Commit

Permalink
ostream buffer growth was broken
Browse files Browse the repository at this point in the history
It only grew by 3/2 of the needed size instead of the needed capacity,
which could be extremely slow when growing by a constant amount
many times.
  • Loading branch information
pixelflinger committed Nov 13, 2024
1 parent 51392c7 commit 5dfd285
Show file tree
Hide file tree
Showing 2 changed files with 16 additions and 15 deletions.
4 changes: 2 additions & 2 deletions libs/utils/include/utils/ostream.h
Original file line number Diff line number Diff line change
Expand Up @@ -95,11 +95,11 @@ class UTILS_PUBLIC ostream : protected utils::PrivateImplementation<ostream_> {
size_t length() const noexcept;

private:
void reserve(size_t newSize) noexcept;
void reserve(size_t newCapacity) noexcept;

char* buffer = nullptr; // buffer address
char* curr = nullptr; // current pointer
size_t size = 0; // size remaining
size_t sizeRemaining = 0; // size remaining
size_t capacity = 0; // total capacity of the buffer
};

Expand Down
27 changes: 14 additions & 13 deletions libs/utils/src/ostream.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -237,23 +237,23 @@ ostream::Buffer::~Buffer() noexcept {

void ostream::Buffer::advance(ssize_t n) noexcept {
if (n > 0) {
size_t const written = n < size ? size_t(n) : size;
size_t const written = n < sizeRemaining ? size_t(n) : sizeRemaining;
curr += written;
size -= written;
sizeRemaining -= written;
}
}

void ostream::Buffer::reserve(size_t newSize) noexcept {
void ostream::Buffer::reserve(size_t newCapacity) noexcept {
size_t const offset = curr - buffer;
if (buffer == nullptr) {
buffer = (char*)malloc(newSize);
buffer = (char*)malloc(newCapacity);
} else {
buffer = (char*)realloc(buffer, newSize);
buffer = (char*)realloc(buffer, newCapacity);
}
assert(buffer);
capacity = newSize;
capacity = newCapacity;
curr = buffer + offset;
size = capacity - offset;
sizeRemaining = capacity - offset;
}

void ostream::Buffer::reset() noexcept {
Expand All @@ -264,21 +264,22 @@ void ostream::Buffer::reset() noexcept {
capacity = 1024;
}
curr = buffer;
size = capacity;
sizeRemaining = capacity;
}

size_t ostream::Buffer::length() const noexcept {
return curr - buffer;
}

std::pair<char*, size_t> ostream::Buffer::grow(size_t s) noexcept {
if (UTILS_UNLIKELY(size < s)) {
size_t const used = curr - buffer;
size_t const newCapacity = std::max(size_t(32), used + (s * 3 + 1) / 2); // 32 bytes minimum
if (UTILS_UNLIKELY(sizeRemaining < s)) {
size_t const usedSize = curr - buffer;
size_t const neededCapacity = usedSize + s;
size_t const newCapacity = std::max(size_t(32), (neededCapacity * 3 + 1) / 2); // 32 bytes minimum
reserve(newCapacity);
assert(size >= s);
assert(sizeRemaining >= s);
}
return { curr, size };
return { curr, sizeRemaining };
}

} // namespace utils::io

0 comments on commit 5dfd285

Please sign in to comment.