SliceBuffer: lazy initialization

Avoid page faults on MPD startup.  This saves a lot of memory for an
idle MPD.
This commit is contained in:
Max Kellermann 2013-01-04 20:27:29 +01:00
parent e3a2bd3a1e
commit 447a86c922
1 changed files with 21 additions and 13 deletions

View File

@ -47,6 +47,13 @@ class SliceBuffer {
*/
const unsigned n_max;
/**
* The number of slices that are initialized. This is used to
* avoid page faulting on the new allocation, so the kernel
* does not need to reserve physical memory pages.
*/
unsigned n_initialized;
/**
* The number of slices currently allocated.
*/
@ -61,15 +68,9 @@ class SliceBuffer {
public:
SliceBuffer(unsigned _count)
:n_max(_count), n_allocated(0),
data(g_new(Slice, n_max)), available(data) {
:n_max(_count), n_initialized(0), n_allocated(0),
data(g_new(Slice, n_max)), available(nullptr) {
assert(n_max > 0);
Slice *const last = data + n_max - 1;
for (Slice *slice = data; slice != last; ++slice)
slice->next = slice + 1;
last->next = nullptr;
}
~SliceBuffer() {
@ -97,12 +98,18 @@ public:
template<typename... Args>
T *Allocate(Args&&... args) {
assert(n_allocated <= n_max);
assert(n_initialized <= n_max);
assert(n_allocated <= n_initialized);
if (available == nullptr) {
/* out of (internal) memory, buffer is full */
assert(n_allocated == n_max);
return nullptr;
if (n_initialized == n_max) {
/* out of (internal) memory, buffer is full */
assert(n_allocated == n_max);
return nullptr;
}
available = &data[n_initialized++];
available->next = nullptr;
}
/* allocate a slice */
@ -115,8 +122,9 @@ public:
}
void Free(T *value) {
assert(n_initialized <= n_max);
assert(n_allocated > 0);
assert(n_allocated <= n_max);
assert(n_allocated <= n_initialized);
Slice *slice = reinterpret_cast<Slice *>(value);
assert(slice >= data && slice < data + n_max);