class CordBuffer

Defined at line 105 of file ../../third_party/abseil-cpp/absl/strings/cord_buffer.h

CordBuffer

CordBuffer manages memory buffers for purposes such as zero-copy APIs as well

as applications building cords with large data requiring granular control

over the allocation and size of cord data. For example, a function creating

a cord of random data could use a CordBuffer as follows:

absl::Cord CreateRandomCord(size_t length) {

absl::Cord cord;

while (length > 0) {

CordBuffer buffer = CordBuffer::CreateWithDefaultLimit(length);

absl::Span

<char

> data = buffer.available_up_to(length);

FillRandomValues(data.data(), data.size());

buffer.IncreaseLengthBy(data.size());

cord.Append(std::move(buffer));

length -= data.size();

}

return cord;

}

CordBuffer instances are by default limited to a capacity of `kDefaultLimit`

bytes. `kDefaultLimit` is currently just under 4KiB, but this default may

change in the future and/or for specific architectures. The default limit is

aimed to provide a good trade-off between performance and memory overhead.

Smaller buffers typically incur more compute cost while larger buffers are

more CPU efficient but create significant memory overhead because of such

allocations being less granular. Using larger buffers may also increase the

risk of memory fragmentation.

Applications create a buffer using one of the `CreateWithDefaultLimit()` or

`CreateWithCustomLimit()` methods. The returned instance will have a non-zero

capacity and a zero length. Applications use the `data()` method to set the

contents of the managed memory, and once done filling the buffer, use the

`IncreaseLengthBy()` or 'SetLength()' method to specify the length of the

initialized data before adding the buffer to a Cord.

The `CreateWithCustomLimit()` method is intended for applications needing

larger buffers than the default memory limit, allowing the allocation of up

to a capacity of `kCustomLimit` bytes minus some minimum internal overhead.

The usage of `CreateWithCustomLimit()` should be limited to only those use

cases where the distribution of the input is relatively well known, and/or

where the trade-off between the efficiency gains outweigh the risk of memory

fragmentation. See the documentation for `CreateWithCustomLimit()` for more

information on using larger custom limits.

The capacity of a `CordBuffer` returned by one of the `Create` methods may

be larger than the requested capacity due to rounding, alignment and

granularity of the memory allocator. Applications should use the `capacity`

method to obtain the effective capacity of the returned instance as

demonstrated in the provided example above.

CordBuffer is a move-only class. All references into the managed memory are

invalidated when an instance is moved into either another CordBuffer instance

or a Cord. Writing to a location obtained by a previous call to `data()`

after an instance was moved will lead to undefined behavior.

A `moved from` CordBuffer instance will have a valid, but empty state.

CordBuffer is thread compatible.

Public Members

static const size_t kDefaultLimit
static const size_t kCustomLimit

Public Methods

void CordBuffer ()

Creates an empty CordBuffer.

Defined at line 123 of file ../../third_party/abseil-cpp/absl/strings/cord_buffer.h

void CordBuffer (const CordBuffer & )

Defined at line 132 of file ../../third_party/abseil-cpp/absl/strings/cord_buffer.h

CordBuffer & operator= (const CordBuffer & )

Defined at line 133 of file ../../third_party/abseil-cpp/absl/strings/cord_buffer.h

void ~CordBuffer ()

Destroys this CordBuffer instance and, if not empty, releases any memory

managed by this instance, invalidating previously returned references.

Defined at line 510 of file ../../third_party/abseil-cpp/absl/strings/cord_buffer.h

void CordBuffer (CordBuffer && rhs)

CordBuffer is move-only

Defined at line 516 of file ../../third_party/abseil-cpp/absl/strings/cord_buffer.h

CordBuffer & operator= (CordBuffer && )

Defined at line 520 of file ../../third_party/abseil-cpp/absl/strings/cord_buffer.h

size_t MaximumPayload ()

CordBuffer::MaximumPayload()

Returns the guaranteed maximum payload for a CordBuffer returned by the

`CreateWithDefaultLimit()` method. While small, each internal buffer inside

a Cord incurs an overhead to manage the length, type and reference count

for the buffer managed inside the cord tree. Applications can use this

method to get approximate number of buffers required for a given byte

size, etc.

For example:

const size_t payload = absl::CordBuffer::MaximumPayload();

const size_t buffer_count = (total_size + payload - 1) / payload;

buffers.reserve(buffer_count);

Defined at line 457 of file ../../third_party/abseil-cpp/absl/strings/cord_buffer.h

size_t MaximumPayload (size_t block_size)

Overload to the above `MaximumPayload()` except that it returns the

maximum payload for a CordBuffer returned by the `CreateWithCustomLimit()`

method given the provided `block_size`.

Defined at line 461 of file ../../third_party/abseil-cpp/absl/strings/cord_buffer.h

CordBuffer CreateWithDefaultLimit (size_t capacity)

CordBuffer::CreateWithDefaultLimit()

Creates a CordBuffer instance of the desired `capacity`, capped at the

default limit `kDefaultLimit`. The returned buffer has a guaranteed

capacity of at least `min(kDefaultLimit, capacity)`. See the class comments

for more information on buffer capacities and intended usage.

Defined at line 465 of file ../../third_party/abseil-cpp/absl/strings/cord_buffer.h

CordBuffer CreateWithCustomLimit (size_t block_size, size_t capacity)

CordBuffer::CreateWithCustomLimit()

Creates a CordBuffer instance of the desired `capacity` rounded to an

appropriate power of 2 size less than, or equal to `block_size`.

Requires `block_size` to be a power of 2.

If `capacity` is less than or equal to `kDefaultLimit`, then this method

behaves identical to `CreateWithDefaultLimit`, which means that the caller

is guaranteed to get a buffer of at least the requested capacity.

If `capacity` is greater than or equal to `block_size`, then this method

returns a buffer with an `allocated size` of `block_size` bytes. Otherwise,

this methods returns a buffer with a suitable smaller power of 2 block size

to satisfy the request. The actual size depends on a number of factors, and

is typically (but not necessarily) the highest or second highest power of 2

value less than or equal to `capacity`.

The 'allocated size' includes a small amount of overhead required for

internal state, which is currently 13 bytes on 64-bit platforms. For

example: a buffer created with `block_size` and `capacity' set to 8KiB

will have an allocated size of 8KiB, and an effective internal `capacity`

of 8KiB - 13 = 8179 bytes.

To demonstrate this in practice, let's assume we want to read data from

somewhat larger files using approximately 64KiB buffers:

absl::Cord ReadFromFile(int fd, size_t n) {

absl::Cord cord;

while (n > 0) {

CordBuffer buffer = CordBuffer::CreateWithCustomLimit(64

<

<

10, n);

absl::Span

<char

> data = buffer.available_up_to(n);

ReadFileDataOrDie(fd, data.data(), data.size());

buffer.IncreaseLengthBy(data.size());

cord.Append(std::move(buffer));

n -= data.size();

}

return cord;

}

If we'd use this function to read a file of 659KiB, we may get the

following pattern of allocated cord buffer sizes:

CreateWithCustomLimit(64KiB, 674816) --> ~64KiB (65523)

CreateWithCustomLimit(64KiB, 674816) --> ~64KiB (65523)

...

CreateWithCustomLimit(64KiB, 19586) --> ~16KiB (16371)

CreateWithCustomLimit(64KiB, 3215) --> 3215 (at least 3215)

The reason the method returns a 16K buffer instead of a roughly 19K buffer

is to reduce memory overhead and fragmentation risks. Using carefully

chosen power of 2 values reduces the entropy of allocated memory sizes.

Additionally, let's assume we'd use the above function on files that are

generally smaller than 64K. If we'd use 'precise' sized buffers for such

files, than we'd get a very wide distribution of allocated memory sizes

rounded to 4K page sizes, and we'd end up with a lot of unused capacity.

In general, application should only use custom sizes if the data they are

consuming or storing is expected to be many times the chosen block size,

and be based on objective data and performance metrics. For example, a

compress function may work faster and consume less CPU when using larger

buffers. Such an application should pick a size offering a reasonable

trade-off between expected data size, compute savings with larger buffers,

and the cost or fragmentation effect of larger buffers.

Applications must pick a reasonable spot on that curve, and make sure their

data meets their expectations in size distributions such as "mostly large".

Defined at line 505 of file ../../third_party/abseil-cpp/absl/strings/cord_buffer.h

absl::Span<char> available ()

CordBuffer::available()

Returns the span delineating the available capacity in this buffer

which is defined as `{ data() + length(), capacity() - length() }`.

Defined at line 527 of file ../../third_party/abseil-cpp/absl/strings/cord_buffer.h

absl::Span<char> available_up_to (size_t size)

CordBuffer::available_up_to()

Returns the span delineating the available capacity in this buffer limited

to `size` bytes. This is equivalent to `available().subspan(0, size)`.

Defined at line 531 of file ../../third_party/abseil-cpp/absl/strings/cord_buffer.h

char * data ()

CordBuffer::data()

Returns a non-null reference to the data managed by this instance.

Applications are allowed to write up to `capacity` bytes of instance data.

CordBuffer data is uninitialized by default. Reading data from an instance

that has not yet been initialized will lead to undefined behavior.

Defined at line 535 of file ../../third_party/abseil-cpp/absl/strings/cord_buffer.h

const char * data ()

Defined at line 539 of file ../../third_party/abseil-cpp/absl/strings/cord_buffer.h

size_t length ()

CordBuffer::length()

Returns the length of this instance. The default length of a CordBuffer is

0, indicating an 'empty' CordBuffer. Applications must specify the length

of the data in a CordBuffer before adding it to a Cord.

Defined at line 547 of file ../../third_party/abseil-cpp/absl/strings/cord_buffer.h

size_t capacity ()

CordBuffer::capacity()

Returns the capacity of this instance. All instances have a non-zero

capacity: default and `moved from` instances have a small internal buffer.

Defined at line 543 of file ../../third_party/abseil-cpp/absl/strings/cord_buffer.h

void IncreaseLengthBy (size_t n)

CordBuffer::IncreaseLengthBy()

Increases the length of this buffer by the specified 'n' bytes.

Applications must make sure all data in this buffer up to the new length

has been initialized before adding a CordBuffer to a Cord: failure to do so

will lead to undefined behavior. Requires `length() + n

<

= capacity()`.

Typically, applications will use 'available_up_to()` to get a span of the

desired capacity, and use `span.size()` to increase the length as in:

absl::Span

<char

> span = buffer.available_up_to(desired);

buffer.IncreaseLengthBy(span.size());

memcpy(span.data(), src, span.size());

etc...

Defined at line 560 of file ../../third_party/abseil-cpp/absl/strings/cord_buffer.h

void SetLength (size_t length)

CordBuffer::SetLength()

Sets the data length of this instance. Applications must make sure all data

of the specified length has been initialized before adding a CordBuffer to

a Cord: failure to do so will lead to undefined behavior.

Setting the length to a small value or zero does not release any memory

held by this CordBuffer instance. Requires `length

<

= capacity()`.

Applications should preferably use the `IncreaseLengthBy()` method above

in combination with the 'available()` or `available_up_to()` methods.

Defined at line 551 of file ../../third_party/abseil-cpp/absl/strings/cord_buffer.h

Friends

class CordBufferTestPeer
class Cord