Commit b0c92e1a authored by Max Kellermann's avatar Max Kellermann

queue/IdTable: lazy-initialize the "data" array

With large "max_playlist_length" settings, the "data" array can be very large, and initializing it during MPD startup causes page faults, resulting in allocation of physical RAM. This commit postpones the initialization until the queue is really large, to avoid wasting memory.
parent ead5bcf0
...@@ -31,6 +31,15 @@ ...@@ -31,6 +31,15 @@
class IdTable { class IdTable {
const unsigned size; const unsigned size;
/**
* How many members of "data" are initialized?
*
* The initial value is 1 and not 0 because the first element
* of the array is never used, because 0 is not a valid song
* id.
*/
unsigned initialized = 1;
unsigned next; unsigned next;
int *const data; int *const data;
...@@ -38,7 +47,6 @@ class IdTable { ...@@ -38,7 +47,6 @@ class IdTable {
public: public:
IdTable(unsigned _size) noexcept IdTable(unsigned _size) noexcept
:size(_size), next(1), data(new int[size]) { :size(_size), next(1), data(new int[size]) {
std::fill_n(data, size, -1);
} }
~IdTable() noexcept { ~IdTable() noexcept {
...@@ -49,14 +57,14 @@ public: ...@@ -49,14 +57,14 @@ public:
IdTable &operator=(const IdTable &) = delete; IdTable &operator=(const IdTable &) = delete;
int IdToPosition(unsigned id) const noexcept { int IdToPosition(unsigned id) const noexcept {
return id < size return id < initialized
? data[id] ? data[id]
: -1; : -1;
} }
unsigned GenerateId() noexcept { unsigned GenerateId() noexcept {
assert(next > 0); assert(next > 0);
assert(next < size); assert(next <= initialized);
while (true) { while (true) {
unsigned id = next; unsigned id = next;
...@@ -65,6 +73,15 @@ public: ...@@ -65,6 +73,15 @@ public:
if (next == size) if (next == size)
next = 1; next = 1;
if (id == initialized) {
/* the caller will initialize
data[id] */
++initialized;
return id;
}
assert(id < initialized);
if (data[id] < 0) if (data[id] < 0)
return id; return id;
} }
...@@ -72,19 +89,20 @@ public: ...@@ -72,19 +89,20 @@ public:
unsigned Insert(unsigned position) noexcept { unsigned Insert(unsigned position) noexcept {
unsigned id = GenerateId(); unsigned id = GenerateId();
assert(id < initialized);
data[id] = position; data[id] = position;
return id; return id;
} }
void Move(unsigned id, unsigned position) noexcept { void Move(unsigned id, unsigned position) noexcept {
assert(id < size); assert(id < initialized);
assert(data[id] >= 0); assert(data[id] >= 0);
data[id] = position; data[id] = position;
} }
void Erase(unsigned id) noexcept { void Erase(unsigned id) noexcept {
assert(id < size); assert(id < initialized);
assert(data[id] >= 0); assert(data[id] >= 0);
data[id] = -1; data[id] = -1;
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment