Commit 11920dbb authored by bell@sanja.is.com.ua's avatar bell@sanja.is.com.ua

New result block allocation strategy

parent 558d88f9
...@@ -179,8 +179,6 @@ create table t2 (a text not null); ...@@ -179,8 +179,6 @@ create table t2 (a text not null);
create table t21 (a text not null); create table t21 (a text not null);
create table t3 (a text not null); create table t3 (a text not null);
insert into t1 values("1111111111111111111111111111111111111111111111111111"); insert into t1 values("1111111111111111111111111111111111111111111111111111");
insert into t11 select * from t1;
insert into t21 select * from t1;
insert into t2 select * from t1; insert into t2 select * from t1;
insert into t1 select * from t2; insert into t1 select * from t2;
insert into t2 select * from t1; insert into t2 select * from t1;
...@@ -196,6 +194,8 @@ insert into t1 select * from t2; ...@@ -196,6 +194,8 @@ insert into t1 select * from t2;
insert into t2 select * from t1; insert into t2 select * from t1;
insert into t1 select * from t2; insert into t1 select * from t2;
insert into t2 select * from t1; insert into t2 select * from t1;
insert into t11 select * from t1;
insert into t21 select * from t1;
insert into t1 select * from t2; insert into t1 select * from t2;
insert into t2 select * from t1; insert into t2 select * from t1;
insert into t1 select * from t2; insert into t1 select * from t2;
......
...@@ -93,8 +93,6 @@ create table t2 (a text not null); ...@@ -93,8 +93,6 @@ create table t2 (a text not null);
create table t21 (a text not null); create table t21 (a text not null);
create table t3 (a text not null); create table t3 (a text not null);
insert into t1 values("1111111111111111111111111111111111111111111111111111"); insert into t1 values("1111111111111111111111111111111111111111111111111111");
insert into t11 select * from t1;
insert into t21 select * from t1;
insert into t2 select * from t1; insert into t2 select * from t1;
insert into t1 select * from t2; insert into t1 select * from t2;
insert into t2 select * from t1; insert into t2 select * from t1;
...@@ -110,6 +108,9 @@ insert into t1 select * from t2; ...@@ -110,6 +108,9 @@ insert into t1 select * from t2;
insert into t2 select * from t1; insert into t2 select * from t1;
insert into t1 select * from t2; insert into t1 select * from t2;
insert into t2 select * from t1; insert into t2 select * from t1;
# t11 and t21 must be over 4Kb (QUERY_CACHE_MIN_RESULT_DATA_SIZE)
insert into t11 select * from t1;
insert into t21 select * from t1;
insert into t1 select * from t2; insert into t1 select * from t2;
insert into t2 select * from t1; insert into t2 select * from t1;
insert into t1 select * from t2; insert into t1 select * from t2;
......
...@@ -273,9 +273,6 @@ TODO list: ...@@ -273,9 +273,6 @@ TODO list:
- Invalidate queries that use innoDB tables changed in transaction & remove - Invalidate queries that use innoDB tables changed in transaction & remove
invalidation by table type invalidation by table type
- Allocate bigger blocks for results (may be we should estimate the
allocatedblock's size dynamicaly) and shrink last block with
results in query_cache_end_of_result.
- Delayed till after-parsing qache answer (for column rights processing) - Delayed till after-parsing qache answer (for column rights processing)
- Optimize cache resizing - Optimize cache resizing
- if new_size < old_size then pack & shrink - if new_size < old_size then pack & shrink
...@@ -657,9 +654,14 @@ void query_cache_end_of_result(NET *net) ...@@ -657,9 +654,14 @@ void query_cache_end_of_result(NET *net)
{ {
DUMP(&query_cache); DUMP(&query_cache);
BLOCK_LOCK_WR(query_block); BLOCK_LOCK_WR(query_block);
Query_cache_query *header = query_block->query();
Query_cache_block *last_result_block = header->result()->prev;
ulong allign_size = ALIGN_SIZE(last_result_block->used);
ulong len = max(query_cache.min_allocation_unit, allign_size);
if (last_result_block->length >= query_cache.min_allocation_unit + len)
query_cache.split_block(last_result_block,len);
STRUCT_UNLOCK(&query_cache.structure_guard_mutex); STRUCT_UNLOCK(&query_cache.structure_guard_mutex);
Query_cache_query *header = query_block->query();
#ifndef DBUG_OFF #ifndef DBUG_OFF
if (header->result() == 0) if (header->result() == 0)
{ {
...@@ -1585,10 +1587,11 @@ Query_cache::append_result_data(Query_cache_block **current_block, ...@@ -1585,10 +1587,11 @@ Query_cache::append_result_data(Query_cache_block **current_block,
*/ */
// Try join blocks if physically next block is free... // Try join blocks if physically next block is free...
ulong tail = data_len - last_block_free_space;
ulong append_min = get_min_append_result_data_size();
if (last_block_free_space < data_len && if (last_block_free_space < data_len &&
append_next_free_block(last_block, append_next_free_block(last_block,
max(data_len - last_block_free_space, max(tail, append_min)))
QUERY_CACHE_MIN_RESULT_DATA_SIZE)))
last_block_free_space = last_block->length - last_block->used; last_block_free_space = last_block->length - last_block->used;
// If no space in last block (even after join) allocate new block // If no space in last block (even after join) allocate new block
if (last_block_free_space < data_len) if (last_block_free_space < data_len)
...@@ -1648,7 +1651,8 @@ my_bool Query_cache::write_result_data(Query_cache_block **result_block, ...@@ -1648,7 +1651,8 @@ my_bool Query_cache::write_result_data(Query_cache_block **result_block,
structure_guard_mutex and copy data. structure_guard_mutex and copy data.
*/ */
my_bool success = allocate_data_chain(result_block, data_len, query_block); my_bool success = allocate_data_chain(result_block, data_len, query_block,
type == Query_cache_block::RES_BEG);
if (success) if (success)
{ {
// It is success (nobody can prevent us write data) // It is success (nobody can prevent us write data)
...@@ -1693,13 +1697,28 @@ my_bool Query_cache::write_result_data(Query_cache_block **result_block, ...@@ -1693,13 +1697,28 @@ my_bool Query_cache::write_result_data(Query_cache_block **result_block,
DBUG_RETURN(success); DBUG_RETURN(success);
} }
inline ulong Query_cache::get_min_first_result_data_size()
{
if (queries_in_cache < QUERY_CACHE_MIN_ESTIMATED_QUERIES_NUMBER)
return min_result_data_size;
ulong avg_result = (query_cache_size - free_memory) / queries_in_cache;
avg_result = min(avg_result, query_cache_limit);
return max(min_result_data_size, avg_result);
}
inline ulong Query_cache::get_min_append_result_data_size()
{
return min_result_data_size;
}
/* /*
Allocate one or more blocks to hold data Allocate one or more blocks to hold data
*/ */
my_bool Query_cache::allocate_data_chain(Query_cache_block **result_block, my_bool Query_cache::allocate_data_chain(Query_cache_block **result_block,
ulong data_len, ulong data_len,
Query_cache_block *query_block) Query_cache_block *query_block,
my_bool first_block)
{ {
ulong all_headers_len = (ALIGN_SIZE(sizeof(Query_cache_block)) + ulong all_headers_len = (ALIGN_SIZE(sizeof(Query_cache_block)) +
ALIGN_SIZE(sizeof(Query_cache_result))); ALIGN_SIZE(sizeof(Query_cache_result)));
...@@ -1708,7 +1727,10 @@ my_bool Query_cache::allocate_data_chain(Query_cache_block **result_block, ...@@ -1708,7 +1727,10 @@ my_bool Query_cache::allocate_data_chain(Query_cache_block **result_block,
DBUG_PRINT("qcache", ("data_len %lu, all_headers_len %lu", DBUG_PRINT("qcache", ("data_len %lu, all_headers_len %lu",
data_len, all_headers_len)); data_len, all_headers_len));
*result_block = allocate_block(max(min_result_data_size,len), ulong min_size = (first_block ?
get_min_first_result_data_size():
get_min_append_result_data_size());
*result_block = allocate_block(max(min_size,len),
min_result_data_size == 0, min_result_data_size == 0,
all_headers_len + min_result_data_size, all_headers_len + min_result_data_size,
1); 1);
...@@ -1732,7 +1754,7 @@ my_bool Query_cache::allocate_data_chain(Query_cache_block **result_block, ...@@ -1732,7 +1754,7 @@ my_bool Query_cache::allocate_data_chain(Query_cache_block **result_block,
Query_cache_block *next_block; Query_cache_block *next_block;
if ((success = allocate_data_chain(&next_block, if ((success = allocate_data_chain(&next_block,
len - new_block->length, len - new_block->length,
query_block))) query_block, first_block)))
double_linked_list_join(new_block, next_block); double_linked_list_join(new_block, next_block);
} }
if (success) if (success)
...@@ -1964,7 +1986,7 @@ Query_cache::allocate_block(ulong len, my_bool not_less, ulong min, ...@@ -1964,7 +1986,7 @@ Query_cache::allocate_block(ulong len, my_bool not_less, ulong min,
if (block != 0) // If we found a suitable block if (block != 0) // If we found a suitable block
{ {
if (block->length > ALIGN_SIZE(len) + min_allocation_unit) if (block->length >= ALIGN_SIZE(len) + min_allocation_unit)
split_block(block,ALIGN_SIZE(len)); split_block(block,ALIGN_SIZE(len));
} }
...@@ -2069,7 +2091,7 @@ void Query_cache::free_memory_block(Query_cache_block *block) ...@@ -2069,7 +2091,7 @@ void Query_cache::free_memory_block(Query_cache_block *block)
} }
void Query_cache::split_block(Query_cache_block *block,ulong len) void Query_cache::split_block(Query_cache_block *block, ulong len)
{ {
DBUG_ENTER("Query_cache::split_block"); DBUG_ENTER("Query_cache::split_block");
Query_cache_block *new_block = (Query_cache_block*)(((byte*) block)+len); Query_cache_block *new_block = (Query_cache_block*)(((byte*) block)+len);
...@@ -2082,7 +2104,11 @@ void Query_cache::split_block(Query_cache_block *block,ulong len) ...@@ -2082,7 +2104,11 @@ void Query_cache::split_block(Query_cache_block *block,ulong len)
new_block->pprev = block; new_block->pprev = block;
new_block->pnext->pprev = new_block; new_block->pnext->pprev = new_block;
if (block->type == Query_cache_block::FREE)
// if block was free then it already joined with all free neighbours
insert_into_free_memory_list(new_block); insert_into_free_memory_list(new_block);
else
free_memory_block(new_block);
DBUG_PRINT("qcache", ("split 0x%lx (%lu) new 0x%lx", DBUG_PRINT("qcache", ("split 0x%lx (%lu) new 0x%lx",
(ulong) block, len, (ulong) new_block)); (ulong) block, len, (ulong) new_block));
......
...@@ -25,14 +25,22 @@ ...@@ -25,14 +25,22 @@
if QUERY_CACHE_MIN_ALLOCATION_UNIT == 0 then if QUERY_CACHE_MIN_ALLOCATION_UNIT == 0 then
QUERY_CACHE_MIN_ALLOCATION_UNIT choosed automaticaly QUERY_CACHE_MIN_ALLOCATION_UNIT choosed automaticaly
*/ */
#define QUERY_CACHE_MIN_ALLOCATION_UNIT 0 #define QUERY_CACHE_MIN_ALLOCATION_UNIT 512
/* inittial size of hashes */ /* inittial size of hashes */
#define QUERY_CACHE_DEF_QUERY_HASH_SIZE 1024 #define QUERY_CACHE_DEF_QUERY_HASH_SIZE 1024
#define QUERY_CACHE_DEF_TABLE_HASH_SIZE 1024 #define QUERY_CACHE_DEF_TABLE_HASH_SIZE 1024
/* minimal result data size when data allocated */ /* minimal result data size when data allocated */
#define QUERY_CACHE_MIN_RESULT_DATA_SIZE 1024 #define QUERY_CACHE_MIN_RESULT_DATA_SIZE 1024*4
/*
start estimation of first result block size only when number of queries
bigger then:
*/
#define QUERY_CACHE_MIN_ESTIMATED_QUERIES_NUMBER 3
/* memory bins size spacing (see at Query_cache::init_cache (sql_cache.cc)) */ /* memory bins size spacing (see at Query_cache::init_cache (sql_cache.cc)) */
#define QUERY_CACHE_MEM_BIN_FIRST_STEP_PWR2 4 #define QUERY_CACHE_MEM_BIN_FIRST_STEP_PWR2 4
...@@ -234,8 +242,7 @@ protected: ...@@ -234,8 +242,7 @@ protected:
query structure we locked an internal query block mutex. query structure we locked an internal query block mutex.
LOCK SEQUENCE (to prevent deadlocks): LOCK SEQUENCE (to prevent deadlocks):
1. structure_guard_mutex 1. structure_guard_mutex
2. query block / table block / free block 2. query block (for operation inside query (query block/results))
3. results blocks (only when must become free).
*/ */
pthread_mutex_t structure_guard_mutex; pthread_mutex_t structure_guard_mutex;
byte *cache; // cache memory byte *cache; // cache memory
...@@ -271,7 +278,8 @@ protected: ...@@ -271,7 +278,8 @@ protected:
void free_query(Query_cache_block *point); void free_query(Query_cache_block *point);
my_bool allocate_data_chain(Query_cache_block **result_block, my_bool allocate_data_chain(Query_cache_block **result_block,
ulong data_len, ulong data_len,
Query_cache_block *query_block); Query_cache_block *query_block,
my_bool first_block);
void invalidate_table(TABLE_LIST *table); void invalidate_table(TABLE_LIST *table);
void invalidate_table(TABLE *table); void invalidate_table(TABLE *table);
void invalidate_table(Query_cache_block *table_block); void invalidate_table(Query_cache_block *table_block);
...@@ -328,6 +336,8 @@ protected: ...@@ -328,6 +336,8 @@ protected:
Query_cache_block *parent, Query_cache_block *parent,
Query_cache_block::block_type Query_cache_block::block_type
type=Query_cache_block::RESULT); type=Query_cache_block::RESULT);
inline ulong get_min_first_result_data_size();
inline ulong get_min_append_result_data_size();
Query_cache_block *allocate_block(ulong len, my_bool not_less, Query_cache_block *allocate_block(ulong len, my_bool not_less,
ulong min, ulong min,
my_bool under_guard=0); my_bool under_guard=0);
......
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