I remember reading many years ago why 1.5 is preferred over two, at least as applied to C++ (this probably doesn’t apply to managed languages, where the runtime system can relocate objects at will).
The reasoning is this:
- Say you start with a 16-byte allocation.
- When you need more, you allocate 32 bytes, then free up 16 bytes. This leaves a 16-byte hole in memory.
- When you need more, you allocate 64 bytes, freeing up the 32 bytes. This leaves a 48-byte hole (if the 16 and 32 were adjacent).
- When you need more, you allocate 128 bytes, freeing up the 64 bytes. This leaves a 112-byte hole (assuming all previous allocations are adjacent).
- And so and and so forth.
The idea is that, with a 2x expansion, there is no point in time that the resulting hole is ever going to be large enough to reuse for the next allocation. Using a 1.5x allocation, we have this instead:
- Start with 16 bytes.
- When you need more, allocate 24 bytes, then free up the 16, leaving a 16-byte hole.
- When you need more, allocate 36 bytes, then free up the 24, leaving a 40-byte hole.
- When you need more, allocate 54 bytes, then free up the 36, leaving a 76-byte hole.
- When you need more, allocate 81 bytes, then free up the 54, leaving a 130-byte hole.
- When you need more, use 122 bytes (rounding up) from the 130-byte hole.