Commit 00182991 authored by unknown's avatar unknown

Bug#25175 Too much memory used by MySQL grant system

Each time the server reloads privileges containing table grants, the 
system will allocate too much memory than needed because of badly
chosen growth prediction in the underlying dynamic arrays.

This patch introduces a new signature to the hash container initializer
which enables a much more pessimistic approach in favour for more
efficient memory useage.

This patch was supplied by Google Inc.


include/hash.h:
  * New signature for _hash_init.
  * Defined new function hash_init2 which takes growth_size argument.
mysys/hash.c:
  * New signature for _hash_init.
sql/sql_acl.cc:
  * Changed hash_init signature so that it takes a 'growth_size' smaller
  than the default. Each time a GRANT_TABLE is allocated a pre-allocated
  dynamic array is instantiated. A large growth size can result in too
  many unused hash-entries per table-entry and thus be a waste of free
  memory.
parent 269ccba9
...@@ -47,8 +47,9 @@ typedef struct st_hash { ...@@ -47,8 +47,9 @@ typedef struct st_hash {
/* A search iterator state */ /* A search iterator state */
typedef uint HASH_SEARCH_STATE; typedef uint HASH_SEARCH_STATE;
#define hash_init(A,B,C,D,E,F,G,H) _hash_init(A,B,C,D,E,F,G, H CALLER_INFO) #define hash_init(A,B,C,D,E,F,G,H) _hash_init(A,0,B,C,D,E,F,G,H CALLER_INFO)
my_bool _hash_init(HASH *hash, CHARSET_INFO *charset, #define hash_init2(A,B,C,D,E,F,G,H,I) _hash_init(A,B,C,D,E,F,G,H,I CALLER_INFO)
my_bool _hash_init(HASH *hash, uint growth_size,CHARSET_INFO *charset,
ulong default_array_elements, size_t key_offset, ulong default_array_elements, size_t key_offset,
size_t key_length, hash_get_key get_key, size_t key_length, hash_get_key get_key,
void (*free_element)(void*), uint flags CALLER_INFO_PROTO); void (*free_element)(void*), uint flags CALLER_INFO_PROTO);
...@@ -69,7 +70,7 @@ my_bool hash_check(HASH *hash); /* Only in debug library */ ...@@ -69,7 +70,7 @@ my_bool hash_check(HASH *hash); /* Only in debug library */
#define hash_clear(H) bzero((char*) (H),sizeof(*(H))) #define hash_clear(H) bzero((char*) (H),sizeof(*(H)))
#define hash_inited(H) ((H)->array.buffer != 0) #define hash_inited(H) ((H)->array.buffer != 0)
#define hash_init_opt(A,B,C,D,E,F,G,H) \ #define hash_init_opt(A,B,C,D,E,F,G,H) \
(!hash_inited(A) && _hash_init(A,B,C,D,E,F,G, H CALLER_INFO)) (!hash_inited(A) && _hash_init(A,0,B,C,D,E,F,G, H CALLER_INFO))
#ifdef __cplusplus #ifdef __cplusplus
} }
......
...@@ -46,7 +46,7 @@ static uint calc_hash(const HASH *hash, const uchar *key, size_t length) ...@@ -46,7 +46,7 @@ static uint calc_hash(const HASH *hash, const uchar *key, size_t length)
} }
my_bool my_bool
_hash_init(HASH *hash,CHARSET_INFO *charset, _hash_init(HASH *hash,uint growth_size, CHARSET_INFO *charset,
ulong size, size_t key_offset, size_t key_length, ulong size, size_t key_offset, size_t key_length,
hash_get_key get_key, hash_get_key get_key,
void (*free_element)(void*),uint flags CALLER_INFO_PROTO) void (*free_element)(void*),uint flags CALLER_INFO_PROTO)
...@@ -55,7 +55,8 @@ _hash_init(HASH *hash,CHARSET_INFO *charset, ...@@ -55,7 +55,8 @@ _hash_init(HASH *hash,CHARSET_INFO *charset,
DBUG_PRINT("enter",("hash: 0x%lx size: %u", (long) hash, (uint) size)); DBUG_PRINT("enter",("hash: 0x%lx size: %u", (long) hash, (uint) size));
hash->records=0; hash->records=0;
if (my_init_dynamic_array_ci(&hash->array,sizeof(HASH_LINK),size,0)) if (my_init_dynamic_array_ci(&hash->array, sizeof(HASH_LINK), size,
growth_size))
{ {
hash->free=0; /* Allow call to hash_free */ hash->free=0; /* Allow call to hash_free */
DBUG_RETURN(1); DBUG_RETURN(1);
......
...@@ -2281,7 +2281,7 @@ GRANT_TABLE::GRANT_TABLE(const char *h, const char *d,const char *u, ...@@ -2281,7 +2281,7 @@ GRANT_TABLE::GRANT_TABLE(const char *h, const char *d,const char *u,
const char *t, ulong p, ulong c) const char *t, ulong p, ulong c)
:GRANT_NAME(h,d,u,t,p), cols(c) :GRANT_NAME(h,d,u,t,p), cols(c)
{ {
(void) hash_init(&hash_columns,system_charset_info, (void) hash_init2(&hash_columns,4,system_charset_info,
0,0,0, (hash_get_key) get_key_column,0,0); 0,0,0, (hash_get_key) get_key_column,0,0);
} }
...@@ -2329,7 +2329,7 @@ GRANT_TABLE::GRANT_TABLE(TABLE *form, TABLE *col_privs) ...@@ -2329,7 +2329,7 @@ GRANT_TABLE::GRANT_TABLE(TABLE *form, TABLE *col_privs)
cols= (ulong) form->field[7]->val_int(); cols= (ulong) form->field[7]->val_int();
cols = fix_rights_for_column(cols); cols = fix_rights_for_column(cols);
(void) hash_init(&hash_columns,system_charset_info, (void) hash_init2(&hash_columns,4,system_charset_info,
0,0,0, (hash_get_key) get_key_column,0,0); 0,0,0, (hash_get_key) get_key_column,0,0);
if (cols) if (cols)
{ {
......
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