Commit d56453be authored by marko's avatar marko

branches/zip: buf_LRU_search_and_free_block(): Avoid freeing compressed-only

pages when they do not occupy too much of the buffer pool.

buf0buddy.c, buf0buddy.h: Export buf_buddy_n_frames and buf_buddy_min_n_frames.
parent e67d5c76
...@@ -17,20 +17,23 @@ Created December 2006 by Marko Makela ...@@ -17,20 +17,23 @@ Created December 2006 by Marko Makela
#include "buf0flu.h" #include "buf0flu.h"
#include "page0zip.h" #include "page0zip.h"
/* Statistic counters, protected by buf_pool->mutex */ /* Statistic counters */
/** Number of frames allocated from the buffer pool to the buddy system */ /** Number of frames allocated from the buffer pool to the buddy system.
static ulint buf_buddy_n_frames; Protected by buf_pool->mutex. */
/** Counts of blocks allocated from the buddy system */ ulint buf_buddy_n_frames;
/** Counts of blocks allocated from the buddy system.
Protected by buf_pool->mutex. */
static ulint buf_buddy_used[BUF_BUDDY_SIZES + 1]; static ulint buf_buddy_used[BUF_BUDDY_SIZES + 1];
/** Counts of blocks relocated by the buddy system */ /** Counts of blocks relocated by the buddy system.
Protected by buf_pool->mutex. */
static ib_uint64_t buf_buddy_relocated[BUF_BUDDY_SIZES + 1]; static ib_uint64_t buf_buddy_relocated[BUF_BUDDY_SIZES + 1];
/** Preferred minimum number of frames allocated from the buffer pool /** Preferred minimum number of frames allocated from the buffer pool
to the buddy system. When this number is exceeded, the buddy allocator to the buddy system. When this number is exceeded, the buddy allocator
will not try to free clean compressed-only pages in order to satisfy will not try to free clean compressed-only pages in order to satisfy
an allocation request. Protected by buf_pool->mutex. */ an allocation request. Protected by buf_pool->mutex. */
static ulint buf_buddy_min_n_frames = ULINT_UNDEFINED; ulint buf_buddy_min_n_frames = ULINT_UNDEFINED;
/************************************************************************** /**************************************************************************
Get the offset of the buddy of a compressed page frame. */ Get the offset of the buddy of a compressed page frame. */
......
...@@ -264,7 +264,6 @@ buf_LRU_search_and_free_block( ...@@ -264,7 +264,6 @@ buf_LRU_search_and_free_block(
of the LRU list */ of the LRU list */
{ {
buf_page_t* bpage; buf_page_t* bpage;
ulint distance = 0;
ibool freed; ibool freed;
mutex_enter(&(buf_pool->mutex)); mutex_enter(&(buf_pool->mutex));
...@@ -272,25 +271,88 @@ buf_LRU_search_and_free_block( ...@@ -272,25 +271,88 @@ buf_LRU_search_and_free_block(
freed = FALSE; freed = FALSE;
bpage = UT_LIST_GET_LAST(buf_pool->LRU); bpage = UT_LIST_GET_LAST(buf_pool->LRU);
while (bpage != NULL) { if (UNIV_UNLIKELY(n_iterations > 10)) {
mutex_t* block_mutex = buf_page_get_mutex(bpage); /* The buffer pool is scarce. Search the whole
LRU list, and also free any compressed pages. */
while (bpage != NULL) {
mutex_t* block_mutex
= buf_page_get_mutex(bpage);
mutex_enter(block_mutex);
/* Discard also the compressed page. */
freed = buf_LRU_free_block(bpage, TRUE);
if (!freed && bpage->zip.data) {
/* Could not free the compressed page;
try freeing the uncompressed page then. */
freed = buf_LRU_free_block(bpage, FALSE);
}
mutex_exit(block_mutex);
mutex_enter(block_mutex); if (freed) {
freed = buf_LRU_free_block(bpage, n_iterations > 10);
mutex_exit(block_mutex); break;
}
bpage = UT_LIST_GET_PREV(LRU, bpage);
}
} else if (buf_buddy_n_frames > buf_buddy_min_n_frames) {
/* There are enough compressed blocks. Free the
least recently used block, whether or not it
comprises an uncompressed page. */
if (freed) { ulint distance = 100
+ (n_iterations * buf_pool->curr_size) / 10;
break; while (bpage != NULL) {
mutex_t* block_mutex
= buf_page_get_mutex(bpage);
mutex_enter(block_mutex);
/* Preserve any compressed page. */
freed = buf_LRU_free_block(bpage, FALSE);
mutex_exit(block_mutex);
if (freed) {
break;
}
bpage = UT_LIST_GET_PREV(LRU, bpage);
if (!--distance) {
goto func_exit;
}
} }
} else {
/* There are few compressed blocks. Skip compressed-only
blocks in the search for the least recently used block
that can be freed. Preserve any compressed page. */
ulint distance = 100
+ (n_iterations * buf_pool->curr_size) / 10;
bpage = UT_LIST_GET_PREV(LRU, bpage); while (bpage != NULL) {
distance++; if (buf_page_get_state(bpage)
== BUF_BLOCK_FILE_PAGE) {
if (n_iterations <= 10 buf_block_t* block = (buf_block_t*) bpage;
&& distance > 100 + (n_iterations * buf_pool->curr_size) mutex_enter(&block->mutex);
/ 10) { /* Preserve any compressed page. */
goto func_exit; freed = buf_LRU_free_block(bpage, FALSE);
mutex_exit(&block->mutex);
if (freed) {
break;
}
}
bpage = UT_LIST_GET_PREV(LRU, bpage);
if (!--distance) {
goto func_exit;
}
} }
} }
......
...@@ -46,6 +46,15 @@ buf_buddy_free( ...@@ -46,6 +46,15 @@ buf_buddy_free(
ulint size) /* in: block size, up to UNIV_PAGE_SIZE */ ulint size) /* in: block size, up to UNIV_PAGE_SIZE */
__attribute__((nonnull)); __attribute__((nonnull));
/** Number of frames allocated from the buffer pool to the buddy system.
Protected by buf_pool->mutex. */
extern ulint buf_buddy_n_frames;
/** Preferred minimum number of frames allocated from the buffer pool
to the buddy system. When this number is exceeded, the buddy allocator
will not try to free clean compressed-only pages in order to satisfy
an allocation request. Protected by buf_pool->mutex. */
extern ulint buf_buddy_min_n_frames;
#ifndef UNIV_NONINL #ifndef UNIV_NONINL
# include "buf0buddy.ic" # include "buf0buddy.ic"
#endif #endif
......
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