Commit 9c168f32 authored by Marko Mäkelä's avatar Marko Mäkelä

Bug #57707 InnoDB buf_page_t size has doubled on 32-bit systems

buf_page_t: Remove the buf_pool pointer. Add buf_pool_index:6 next to
buf_fix_count:19 (it was buf_fix_count:25). This will limit the number
of concurrent transactions to somewhere around 524,288.

buf_pool_index(buf_pool): A new function to determine the index of a
buffer pool in buf_pool_ptr[].

buf_pool_ptr: Make this a dynamically allocated array instead of an
array of pointers. Allocate the array in buf_pool_init() and free in
buf_pool_free().

buf_pool_free_instance(): No longer free the buf_pool object, as it is
allocated from a big array.

buf_pool_from_bpage(), buf_pool_from_block(): Move the definitions to
the beginning of the files, because some compilers have (had) problems
with forward definitions of inline functions. Calculate the buffer
pool from buf_pool_index.

buf_pool_from_array(): Add debug assertions for input validation.
parent 548289ee
...@@ -246,8 +246,8 @@ static const int WAIT_FOR_READ = 5000; ...@@ -246,8 +246,8 @@ static const int WAIT_FOR_READ = 5000;
/** Number of attemtps made to read in a page in the buffer pool */ /** Number of attemtps made to read in a page in the buffer pool */
static const ulint BUF_PAGE_READ_MAX_RETRIES = 100; static const ulint BUF_PAGE_READ_MAX_RETRIES = 100;
/** The buffer buf_pool of the database */ /** The buffer pools of the database */
UNIV_INTERN buf_pool_t* buf_pool_ptr[MAX_BUFFER_POOLS]; UNIV_INTERN buf_pool_t* buf_pool_ptr;
#if defined UNIV_DEBUG || defined UNIV_BUF_DEBUG #if defined UNIV_DEBUG || defined UNIV_BUF_DEBUG
static ulint buf_dbg_counter = 0; /*!< This is used to insert validation static ulint buf_dbg_counter = 0; /*!< This is used to insert validation
...@@ -858,7 +858,7 @@ buf_block_init( ...@@ -858,7 +858,7 @@ buf_block_init(
block->frame = frame; block->frame = frame;
block->page.buf_pool = buf_pool; block->page.buf_pool_index = buf_pool_index(buf_pool);
block->page.state = BUF_BLOCK_NOT_USED; block->page.state = BUF_BLOCK_NOT_USED;
block->page.buf_fix_count = 0; block->page.buf_fix_count = 0;
block->page.io_fix = BUF_IO_NONE; block->page.io_fix = BUF_IO_NONE;
...@@ -1280,8 +1280,6 @@ buf_pool_free_instance( ...@@ -1280,8 +1280,6 @@ buf_pool_free_instance(
mem_free(buf_pool->chunks); mem_free(buf_pool->chunks);
hash_table_free(buf_pool->page_hash); hash_table_free(buf_pool->page_hash);
hash_table_free(buf_pool->zip_hash); hash_table_free(buf_pool->zip_hash);
mem_free(buf_pool);
buf_pool = NULL;
} }
/********************************************************************//** /********************************************************************//**
...@@ -1294,25 +1292,22 @@ buf_pool_init( ...@@ -1294,25 +1292,22 @@ buf_pool_init(
ulint total_size, /*!< in: size of the total pool in bytes */ ulint total_size, /*!< in: size of the total pool in bytes */
ulint n_instances) /*!< in: number of instances */ ulint n_instances) /*!< in: number of instances */
{ {
ulint i; ulint i;
const ulint size = total_size / n_instances;
ut_ad(n_instances < MAX_BUFFER_POOLS);
ut_ad(n_instances == srv_buf_pool_instances);
/* We create an extra buffer pool instance, this instance is used /* We create an extra buffer pool instance, this instance is used
for flushing the flush lists, to keep track of n_flush for all for flushing the flush lists, to keep track of n_flush for all
the buffer pools and also used as a waiting object during flushing. */ the buffer pools and also used as a waiting object during flushing. */
for (i = 0; i < n_instances; i++) { buf_pool_ptr = mem_zalloc(n_instances * sizeof *buf_pool_ptr);
buf_pool_t* ptr;
ulint size;
ptr = mem_zalloc(sizeof(*ptr));
size = total_size / n_instances; for (i = 0; i < n_instances; i++) {
buf_pool_t* ptr = &buf_pool_ptr[i];
buf_pool_ptr[i] = ptr;
if (buf_pool_init_instance(ptr, size, i) != DB_SUCCESS) { if (buf_pool_init_instance(ptr, size, i) != DB_SUCCESS) {
mem_free(buf_pool_ptr[i]);
/* Free all the instances created so far. */ /* Free all the instances created so far. */
buf_pool_free(i); buf_pool_free(i);
...@@ -1341,8 +1336,10 @@ buf_pool_free( ...@@ -1341,8 +1336,10 @@ buf_pool_free(
for (i = 0; i < n_instances; i++) { for (i = 0; i < n_instances; i++) {
buf_pool_free_instance(buf_pool_from_array(i)); buf_pool_free_instance(buf_pool_from_array(i));
buf_pool_ptr[i] = NULL;
} }
mem_free(buf_pool_ptr);
buf_pool_ptr = NULL;
} }
/********************************************************************//** /********************************************************************//**
...@@ -3685,7 +3682,7 @@ err_exit: ...@@ -3685,7 +3682,7 @@ err_exit:
bpage = buf_buddy_alloc(buf_pool, sizeof *bpage, &lru); bpage = buf_buddy_alloc(buf_pool, sizeof *bpage, &lru);
/* Initialize the buf_pool pointer. */ /* Initialize the buf_pool pointer. */
bpage->buf_pool = buf_pool; bpage->buf_pool_index = buf_pool_index(buf_pool);
/* If buf_buddy_alloc() allocated storage from the LRU list, /* If buf_buddy_alloc() allocated storage from the LRU list,
it released and reacquired buf_pool->mutex. Thus, we must it released and reacquired buf_pool->mutex. Thus, we must
......
...@@ -69,7 +69,7 @@ Created 11/5/1995 Heikki Tuuri ...@@ -69,7 +69,7 @@ Created 11/5/1995 Heikki Tuuri
#define BUF_POOL_WATCH_SIZE 1 /*!< Maximum number of concurrent #define BUF_POOL_WATCH_SIZE 1 /*!< Maximum number of concurrent
buffer pool watches */ buffer pool watches */
extern buf_pool_t* buf_pool_ptr[MAX_BUFFER_POOLS]; /*!< The buffer pools extern buf_pool_t* buf_pool_ptr; /*!< The buffer pools
of the database */ of the database */
#ifdef UNIV_DEBUG #ifdef UNIV_DEBUG
extern ibool buf_debug_prints;/*!< If this is set TRUE, the program extern ibool buf_debug_prints;/*!< If this is set TRUE, the program
...@@ -1034,6 +1034,15 @@ buf_page_address_fold( ...@@ -1034,6 +1034,15 @@ buf_page_address_fold(
ulint space, /*!< in: space id */ ulint space, /*!< in: space id */
ulint offset) /*!< in: offset of the page within space */ ulint offset) /*!< in: offset of the page within space */
__attribute__((const)); __attribute__((const));
/********************************************************************//**
Calculates the index of a buffer pool to the buf_pool[] array.
@return the position of the buffer pool in buf_pool[] */
UNIV_INLINE
ulint
buf_pool_index(
/*===========*/
const buf_pool_t* buf_pool) /*!< in: buffer pool */
__attribute__((nonnull, const));
/******************************************************************//** /******************************************************************//**
Returns the buffer pool instance given a page instance Returns the buffer pool instance given a page instance
@return buf_pool */ @return buf_pool */
...@@ -1065,8 +1074,9 @@ Returns the buffer pool instance given its array index ...@@ -1065,8 +1074,9 @@ Returns the buffer pool instance given its array index
UNIV_INLINE UNIV_INLINE
buf_pool_t* buf_pool_t*
buf_pool_from_array( buf_pool_from_array(
/*====================*/ /*================*/
ulint index); /*!< in: array index to get buffer pool instance from */ ulint index); /*!< in: array index to get
buffer pool instance from */
/******************************************************************//** /******************************************************************//**
Returns the control block of a file page, NULL if not found. Returns the control block of a file page, NULL if not found.
@return block, NULL if not found */ @return block, NULL if not found */
...@@ -1204,8 +1214,13 @@ struct buf_page_struct{ ...@@ -1204,8 +1214,13 @@ struct buf_page_struct{
unsigned io_fix:2; /*!< type of pending I/O operation; unsigned io_fix:2; /*!< type of pending I/O operation;
also protected by buf_pool->mutex also protected by buf_pool->mutex
@see enum buf_io_fix */ @see enum buf_io_fix */
unsigned buf_fix_count:25;/*!< count of how manyfold this block unsigned buf_fix_count:19;/*!< count of how manyfold this block
is currently bufferfixed */ is currently bufferfixed */
unsigned buf_pool_index:6;/*!< index number of the buffer pool
that this block belongs to */
# if MAX_BUFFER_POOLS > 64
# error "MAX_BUFFER_POOLS > 64; redefine buf_pool_index:6"
# endif
/* @} */ /* @} */
#endif /* !UNIV_HOTBACKUP */ #endif /* !UNIV_HOTBACKUP */
page_zip_des_t zip; /*!< compressed page; zip.data page_zip_des_t zip; /*!< compressed page; zip.data
...@@ -1324,8 +1339,6 @@ struct buf_page_struct{ ...@@ -1324,8 +1339,6 @@ struct buf_page_struct{
frees a page in buffer pool */ frees a page in buffer pool */
# endif /* UNIV_DEBUG_FILE_ACCESSES */ # endif /* UNIV_DEBUG_FILE_ACCESSES */
#endif /* !UNIV_HOTBACKUP */ #endif /* !UNIV_HOTBACKUP */
buf_pool_t* buf_pool; /*!< buffer pool instance this
page belongs to */
}; };
/** The buffer control block structure */ /** The buffer control block structure */
......
...@@ -46,6 +46,48 @@ buf_pool_get_curr_size(void) ...@@ -46,6 +46,48 @@ buf_pool_get_curr_size(void)
return(srv_buf_pool_curr_size); return(srv_buf_pool_curr_size);
} }
/********************************************************************//**
Calculates the index of a buffer pool to the buf_pool[] array.
@return the position of the buffer pool in buf_pool[] */
UNIV_INLINE
ulint
buf_pool_index(
/*===========*/
const buf_pool_t* buf_pool) /*!< in: buffer pool */
{
ulint i = buf_pool - buf_pool_ptr;
ut_ad(i < MAX_BUFFER_POOLS);
ut_ad(i < srv_buf_pool_instances);
return(i);
}
/******************************************************************//**
Returns the buffer pool instance given a page instance
@return buf_pool */
UNIV_INLINE
buf_pool_t*
buf_pool_from_bpage(
/*================*/
const buf_page_t* bpage) /*!< in: buffer pool page */
{
ulint i;
i = bpage->buf_pool_index;
ut_ad(i < srv_buf_pool_instances);
return(&buf_pool_ptr[i]);
}
/******************************************************************//**
Returns the buffer pool instance given a block instance
@return buf_pool */
UNIV_INLINE
buf_pool_t*
buf_pool_from_block(
/*================*/
const buf_block_t* block) /*!< in: block */
{
return(buf_pool_from_bpage(&block->page));
}
/*********************************************************************//** /*********************************************************************//**
Gets the current size of buffer buf_pool in pages. Gets the current size of buffer buf_pool in pages.
@return size in pages*/ @return size in pages*/
...@@ -885,33 +927,6 @@ buf_block_buf_fix_dec( ...@@ -885,33 +927,6 @@ buf_block_buf_fix_dec(
#endif #endif
} }
/******************************************************************//**
Returns the buffer pool instance given a page instance
@return buf_pool */
UNIV_INLINE
buf_pool_t*
buf_pool_from_bpage(
/*================*/
const buf_page_t* bpage) /*!< in: buffer pool page */
{
/* Every page must be in some buffer pool. */
ut_ad(bpage->buf_pool != NULL);
return(bpage->buf_pool);
}
/******************************************************************//**
Returns the buffer pool instance given a block instance
@return buf_pool */
UNIV_INLINE
buf_pool_t*
buf_pool_from_block(
/*================*/
const buf_block_t* block) /*!< in: block */
{
return(buf_pool_from_bpage(&block->page));
}
/******************************************************************//** /******************************************************************//**
Returns the buffer pool instance given space and offset of page Returns the buffer pool instance given space and offset of page
@return buffer pool */ @return buffer pool */
...@@ -929,7 +944,7 @@ buf_pool_get( ...@@ -929,7 +944,7 @@ buf_pool_get(
ignored_offset = offset >> 6; /* 2log of BUF_READ_AHEAD_AREA (64)*/ ignored_offset = offset >> 6; /* 2log of BUF_READ_AHEAD_AREA (64)*/
fold = buf_page_address_fold(space, ignored_offset); fold = buf_page_address_fold(space, ignored_offset);
index = fold % srv_buf_pool_instances; index = fold % srv_buf_pool_instances;
return buf_pool_ptr[index]; return(&buf_pool_ptr[index]);
} }
/******************************************************************//** /******************************************************************//**
...@@ -939,10 +954,12 @@ UNIV_INLINE ...@@ -939,10 +954,12 @@ UNIV_INLINE
buf_pool_t* buf_pool_t*
buf_pool_from_array( buf_pool_from_array(
/*================*/ /*================*/
ulint index) /*!< in: array index to get ulint index) /*!< in: array index to get
buffer pool instance from */ buffer pool instance from */
{ {
return buf_pool_ptr[index]; ut_ad(index < MAX_BUFFER_POOLS);
ut_ad(index < srv_buf_pool_instances);
return(&buf_pool_ptr[index]);
} }
/******************************************************************//** /******************************************************************//**
......
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