We have designed a new replacement algorithm, called Multi-Queue (MQ), that satisfies the three properties above. This algorithm maintains blocks with different access frequencies for different periods of time in the second level buffer cache.
The MQ algorithm uses multiple LRU queues: ,
,
,
where
is a parameter. Blocks in
have a longer lifetime in
the cache than those in
(
). MQ also uses a history
buffer
, similarly to the 2Q algorithm [23], to
remember access frequencies of recently evicted blocks for some period
of time.
only keeps block identifiers and their access
frequencies. It is a FIFO queue of limited size.
On a cache hit to block ,
is first removed from the
current LRU queue and then put at the tail of queue
according to
's current access frequency. In other words,
is
a function of the access frequency,
. For
example, for a given frequency
,
can be defined as
. So the 8th access to a block that is already in the second level
buffer cache will promote this block from
to
according to
this
function.
On a cache miss to block , MQ evicts the head of the lowest
non-empty queue from the second level buffer cache in order to make room for
, i.e. MQ starts with the head of queue
when choosing victims
for replacement. If
is empty, then MQ evicts the head block of
, and so on. If block
is the victim, its identifier and
current access frequency are inserted into the tail of the history buffer
. If
is full, the oldest identifier in
will be deleted. If the requested block
is in
, then it
is loaded and its frequency
is set to be the remembered value plus 1, and
then
's entry is removed from
. If
is not in
, it is loaded into the cache and its frequency is set to
1. Finally, block
is inserted into an LRU queue according to the
value of
.
MQ demotes blocks from higher to lower level queues in order to
eventually evict blocks that have been accessed frequently in the
past, but have not been accessed for a long time. MQ does this by
associating a value called with each block in the server
buffer cache. ``Time'' here refers to logical time, measured by number
of accesses. When a block stays in a queue for longer than a
permitted period of time without any access, it is demoted to the next
lower queue. This is easy to implement with LRU queues. When a block
enters a queue, the block's
is set to be
, where
, a tunable parameter, is the time that
each block can be kept in a queue without any access. At each access,
the
of each queue's head block is checked against the
. If the former is less than the latter, it is moved to
the tail of the next lower level queue and the block's
is
reset. Figure 5 gives a pseudo-code outline for the MQ
algorithm.
When equals 1, the MQ algorithm is the LRU algorithm. When
equals 2, the MQ algorithm and the 2Q algorithm [23] both use
two queues and a history buffer. However, MQ uses two LRU queues,
while 2Q uses one FIFO and one LRU queue. MQ demotes blocks from
to
when their life time in
expires, while 2Q does
not make this kind of adjustment. When a block in
(or
) is
evicted in the 2Q algorithm, it is not put into the history buffer
whereas it is with MQ.
Like the 2Q algorithm, MQ has a time complexity of because all
queues are implemented using LRU lists and
is usually very small
(less than 10). At each access, at most
head blocks are examined
for possible demotion. MQ is faster in execution and also much simpler
to implement than algorithms like FBR, LFRU or LRU-K, which have a
time complexity close to
(where
is the number of entries
in the cache) and usually require a heap data structure for
implementation.
MQ satisfies the three properties that a good second level buffer cache
replacement algorithm should have. It satisfies the minimal lifetime
property because warm blocks are kept in high level LRU queues for at
least time, which is usually greater than the
value
of a given workload. It satisfies the frequency-based priority
property because blocks that are accessed more frequently are put into
higher level LRU queues and are, therefore, less likely to be evicted.
It also satisfies the temporal frequency property because MQ demotes
blocks from higher to lower level queues when its lifetime in its
current queue expires. A block that has not been accessed for a long
time will be gradually demoted to queue
and eventually evicted
from the second level buffer cache.