Buffer Pool with variable sized pages. Need a high performance way to coalesce pages when incoming page is larger than the page to be evicted

StackOverflow https://stackoverflow.com/questions/21414196

Question

In an implementation of a database buffer pool (memory pool), I have a buffer which consists of pages in memory.

The pages have different sizes (all integer multiple of 512kb).

Say my eviction policy is LRU (least recently used) but the page I am trying to evict has less size than what I need to replace, If I want to follow LRU as well, I should evict as many LRU pages as necessary to fit in my new page.

Assume I need n recently used pages to be evicted. Yet, these pages are not necessarily consecutive in the buffer/memory pool.

A simple approach I thought about is to coalesce these n pages which means I need to reorder the buffer pool appropriately.

The simplest approach is to copy the whole buffer and overwrite the permanent buffer and update the data types appropriately. Yet this assumes that we have enough RAM to copy the whole buffer for this operation. Is there a clever approach where I don't have to copy the whole buffer?

Thanks

Was it helpful?

Solution

As soon as you have to move buffers around, it won’t be “high performance” in my opinion, however, how about this:

The pages you are going to evict are of a total size of k times page size 512 kB, that is, the size of the incoming page.

The worst-case layout is something like this (four characters (except bars |) == 512 kB):

|X1  |1       |2   |X2  |3       |4       |

The two Xes are the pages to evict. The issue is now that to make the buffers consecutive, you need to move X2 next to X1 (or the other way round). My approach would be to move the pages after X1 towards the right (into X2) in place. We are safe to override X2, because we want to evict it anyways.

That way, we only have to update 3 pages sizes instead of copying the whole buffer.

A more complex problem would be:

|X1  |1   |2       |X2   |3       |X3      |4       |5   |

One can still use the naive algorithm from above, but there are possible optimizations. For example, one can safely move 1 into X2 without touching 2, because it fits there. The same goes for 2, which can be moved into X3.

So in fact, you can always go for the simple moving technique known from dynamic array insertion and swapping, but it might be wise to check for possible optimizations, in this case, enumerate the pages which would have to be moved by the naive algorithm and first try to fit them directly into the to-be-evicted space. Only after that fails (like in the first example) moving should be used.

Copying the whole buffer should only be neccessary if you need atomicity. In that case, the optimized approach from above will also work, but you’ll get into trouble as soon as you cannot fit pages which are in your way into the to-be-evicted pages. You have to recurse in the eviction algorithm in that case to find suitable places, possibly evicting more pages.

Licensed under: CC-BY-SA with attribution
Not affiliated with StackOverflow
scroll top