Skip to content

Commit 0fbb8a0

Browse files
committed
Bug#17473077 EVER INCREASING MEMORY USAGE REPORTED FOR EVENT SCHEDULER
Before this fix, statistics for the memory instrumentation were inaccurate, in the following scenario: At T1, thread A allocates some memory, of size N At T2, thread A gives ownership of the allocated memory to thread B At T3, thread B de allocates the block memory, of size N The event at T1 is instrumented with the performance schema, and an allocation of size N is counted against thread A. The event at T2 is not instrumented. The performance schema is unaware of the memory transfer. The event at T3 is instrumented with the performance schema, and a de allocation of size N is counted against thread B. The problem with this approach is with statistics maintained by thread. When the same code is executed many times (in a loop with the event scheduler), - thread A appears to use an ever increasing amount of memory - thread B appears to consume an ever increasing amount of memory - the global statistics for the server diverge. To resolve this bug, two different fixes are implemented. Which fix to use depends on the nature of the instrumented memory. FIX NUMBER 1 For memory instruments that are by nature measuring a global resource, there is no point in maintaining per thread (and per account, per user, per host) statistics. A typical example of such usage are shared, global structures, like the query cache. For these memory instruments, the performance schema now supports defining the instrument with PSI_GLOBAL_FLAG. For instruments defined as global, the performance schema only maintains the global memory statistics. In this case, nothing needs to be done for event T2, as instrumentation for the allocation (T1) and de allocation (T3) is enough to maintain everything. FIX NUMBER 2 For memory instruments that are by nature measuring a local resource, maintaining statistics per thread is desirable. In order to do so, the performance schema needs to be told about event T2, which is now instrumented explicitly in the code. A new entry point in the instrumentation, PSI_MEMORY_CALL(memory_claim), is used to instrument the change of ownership of a block of memory. When a thread in the server allocates a data structure, starts a child thread, and gives ownership of the memory structure to the child, the code in the child thread now needs to claim ownership of the data. With this added instrumentation, performance schema statistics now reflect more closely how memory is actually used in the server. Various claim_memory_ownership() methods are implemented to support this.
1 parent 637c969 commit 0fbb8a0

Some content is hidden

Large Commits have some content hidden by default. Use the searchbox below for content that may be hidden.

62 files changed

+1076
-10209
lines changed

include/hash.h

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,4 @@
1-
/* Copyright (c) 2000, 2013, Oracle and/or its affiliates. All rights reserved.
1+
/* Copyright (c) 2000, 2015, Oracle and/or its affiliates. All rights reserved.
22
33
This program is free software; you can redistribute it and/or modify
44
it under the terms of the GNU General Public License as published by
@@ -86,6 +86,7 @@ my_bool _my_hash_init(HASH *hash, uint growth_size, CHARSET_INFO *charset,
8686
size_t key_length, my_hash_get_key get_key,
8787
void (*free_element)(void*),
8888
uint flags);
89+
void my_hash_claim(HASH *tree);
8990
void my_hash_free(HASH *tree);
9091
void my_hash_reset(HASH *hash);
9192
uchar *my_hash_element(HASH *hash, ulong idx);

include/my_sys.h

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -752,6 +752,7 @@ extern my_bool insert_dynamic(DYNAMIC_ARRAY *array, const void *element);
752752
extern void *alloc_dynamic(DYNAMIC_ARRAY *array);
753753
extern void *pop_dynamic(DYNAMIC_ARRAY*);
754754
extern void get_dynamic(DYNAMIC_ARRAY *array, void *element, uint array_index);
755+
extern void claim_dynamic(DYNAMIC_ARRAY *array);
755756
extern void delete_dynamic(DYNAMIC_ARRAY *array);
756757
extern void freeze_size(DYNAMIC_ARRAY *array);
757758
static inline void reset_dynamic(DYNAMIC_ARRAY *array)
@@ -778,6 +779,7 @@ extern void init_alloc_root(PSI_memory_key key,
778779
size_t pre_alloc_size);
779780
extern void *alloc_root(MEM_ROOT *mem_root, size_t Size);
780781
extern void *multi_alloc_root(MEM_ROOT *mem_root, ...);
782+
extern void claim_root(MEM_ROOT *root);
781783
extern void free_root(MEM_ROOT *root, myf MyFLAGS);
782784
extern void reset_root_defaults(MEM_ROOT *mem_root, size_t block_size,
783785
size_t prealloc_size);

include/mysql.h.pp

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -99,6 +99,7 @@
9999
void my_net_local_init(NET *net);
100100
void net_end(NET *net);
101101
void net_clear(NET *net, my_bool check_buffer);
102+
void net_claim_memory_ownership(NET *net);
102103
my_bool net_realloc(NET *net, size_t length);
103104
my_bool net_flush(NET *net);
104105
my_bool my_net_write(NET *net,const unsigned char *packet, size_t len);
@@ -253,6 +254,7 @@
253254
#include "my_alloc.h"
254255
#include <mysql/psi/psi_memory.h>
255256
#include "psi_base.h"
257+
struct PSI_thread;
256258
typedef unsigned int PSI_memory_key;
257259
typedef struct st_used_mem
258260
{

include/mysql/psi/psi.h

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -2638,6 +2638,8 @@ struct PSI_v1
26382638
memory_alloc_v1_t memory_alloc;
26392639
/** @sa memory_realloc_v1_t. */
26402640
memory_realloc_v1_t memory_realloc;
2641+
/** @sa memory_claim_v1_t. */
2642+
memory_claim_v1_t memory_claim;
26412643
/** @sa memory_free_v1_t. */
26422644
memory_free_v1_t memory_free;
26432645

include/mysql/psi/psi_abi_v0.h.pp

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -2,6 +2,7 @@
22
#include "psi_base.h"
33
#include "psi_memory.h"
44
#include "psi_base.h"
5+
struct PSI_thread;
56
typedef unsigned int PSI_memory_key;
67
C_MODE_START
78
struct MDL_key;

include/mysql/psi/psi_abi_v1.h.pp

Lines changed: 7 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -2,6 +2,7 @@
22
#include "psi_base.h"
33
#include "psi_memory.h"
44
#include "psi_base.h"
5+
struct PSI_thread;
56
typedef unsigned int PSI_memory_key;
67
struct PSI_memory_info_v1
78
{
@@ -13,11 +14,13 @@
1314
typedef void (*register_memory_v1_t)
1415
(const char *category, struct PSI_memory_info_v1 *info, int count);
1516
typedef PSI_memory_key (*memory_alloc_v1_t)
16-
(PSI_memory_key key, size_t size);
17+
(PSI_memory_key key, size_t size, struct PSI_thread ** owner);
1718
typedef PSI_memory_key (*memory_realloc_v1_t)
18-
(PSI_memory_key key, size_t old_size, size_t new_size);
19+
(PSI_memory_key key, size_t old_size, size_t new_size, struct PSI_thread ** owner);
20+
typedef PSI_memory_key (*memory_claim_v1_t)
21+
(PSI_memory_key key, size_t size, struct PSI_thread ** owner);
1922
typedef void (*memory_free_v1_t)
20-
(PSI_memory_key key, size_t size);
23+
(PSI_memory_key key, size_t size, struct PSI_thread * owner);
2124
typedef struct PSI_memory_info_v1 PSI_memory_info;
2225
C_MODE_START
2326
struct MDL_key;
@@ -805,6 +808,7 @@
805808
register_memory_v1_t register_memory;
806809
memory_alloc_v1_t memory_alloc;
807810
memory_realloc_v1_t memory_realloc;
811+
memory_claim_v1_t memory_claim;
808812
memory_free_v1_t memory_free;
809813
unlock_table_v1_t unlock_table;
810814
create_metadata_lock_v1_t create_metadata_lock;

include/mysql/psi/psi_abi_v2.h.pp

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -2,6 +2,7 @@
22
#include "psi_base.h"
33
#include "psi_memory.h"
44
#include "psi_base.h"
5+
struct PSI_thread;
56
typedef unsigned int PSI_memory_key;
67
struct PSI_memory_info_v2
78
{

include/mysql/psi/psi_base.h

Lines changed: 10 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,4 @@
1-
/* Copyright (c) 2008, 2014, Oracle and/or its affiliates. All rights reserved.
1+
/* Copyright (c) 2008, 2015, Oracle and/or its affiliates. All rights reserved.
22
33
This program is free software; you can redistribute it and/or modify
44
it under the terms of the GNU General Public License as published by
@@ -56,14 +56,21 @@ extern "C" {
5656
*/
5757
#define PSI_FLAG_STAGE_PROGRESS (1 << 3)
5858

59-
#ifdef HAVE_PSI_INTERFACE
60-
6159
/**
6260
Shared Exclusive flag.
6361
Indicates that rwlock support the shared exclusive state.
6462
*/
6563
#define PSI_RWLOCK_FLAG_SX (1 << 4)
6664

65+
/**
66+
Transferable flag.
67+
This flag indicate that an instrumented object can
68+
be created by a thread and destroyed by another thread.
69+
*/
70+
#define PSI_FLAG_TRANSFER (1 << 5)
71+
72+
#ifdef HAVE_PSI_INTERFACE
73+
6774
/**
6875
@def PSI_VERSION_1
6976
Performance Schema Interface number for version 1.

include/mysql/psi/psi_memory.h

Lines changed: 19 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,4 @@
1-
/* Copyright (c) 2013, Oracle and/or its affiliates. All rights reserved.
1+
/* Copyright (c) 2013, 2015, Oracle and/or its affiliates. All rights reserved.
22
33
This program is free software; you can redistribute it and/or modify
44
it under the terms of the GNU General Public License as published by
@@ -39,6 +39,8 @@ extern "C" {
3939
#endif /* DISABLE_ALL_PSI */
4040
#endif /* HAVE_PSI_INTERFACE */
4141

42+
struct PSI_thread;
43+
4244
/**
4345
Instrumented memory key.
4446
To instrument memory, a memory key must be obtained using @c register_memory.
@@ -86,28 +88,41 @@ typedef void (*register_memory_v1_t)
8688
Instrument memory allocation.
8789
@param key the memory instrument key
8890
@param size the size of memory allocated
91+
@param[out] owner the memory owner
8992
@return the effective memory instrument key
9093
*/
9194
typedef PSI_memory_key (*memory_alloc_v1_t)
92-
(PSI_memory_key key, size_t size);
95+
(PSI_memory_key key, size_t size, struct PSI_thread ** owner);
9396

9497
/**
9598
Instrument memory re allocation.
9699
@param key the memory instrument key
97100
@param old_size the size of memory previously allocated
98101
@param new_size the size of memory re allocated
102+
@param[in, out] owner the memory owner
99103
@return the effective memory instrument key
100104
*/
101105
typedef PSI_memory_key (*memory_realloc_v1_t)
102-
(PSI_memory_key key, size_t old_size, size_t new_size);
106+
(PSI_memory_key key, size_t old_size, size_t new_size, struct PSI_thread ** owner);
107+
108+
/**
109+
Instrument memory claim.
110+
@param key the memory instrument key
111+
@param size the size of memory allocated
112+
@param[in, out] owner the memory owner
113+
@return the effective memory instrument key
114+
*/
115+
typedef PSI_memory_key (*memory_claim_v1_t)
116+
(PSI_memory_key key, size_t size, struct PSI_thread ** owner);
103117

104118
/**
105119
Instrument memory free.
106120
@param key the memory instrument key
107121
@param size the size of memory allocated
122+
@param owner the memory owner
108123
*/
109124
typedef void (*memory_free_v1_t)
110-
(PSI_memory_key key, size_t size);
125+
(PSI_memory_key key, size_t size, struct PSI_thread * owner);
111126

112127
/** @} (end of group Group_PSI_v1) */
113128

include/mysql/service_mysql_alloc.h

Lines changed: 5 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,4 @@
1-
/* Copyright (c) 2012, 2013, Oracle and/or its affiliates. All rights reserved.
1+
/* Copyright (c) 2012, 2015, Oracle and/or its affiliates. All rights reserved.
22
33
This program is free software; you can redistribute it and/or modify
44
it under the terms of the GNU General Public License as published by
@@ -32,6 +32,7 @@ typedef int myf_t;
3232

3333
typedef void * (*mysql_malloc_t)(PSI_memory_key key, size_t size, myf_t flags);
3434
typedef void * (*mysql_realloc_t)(PSI_memory_key key, void *ptr, size_t size, myf_t flags);
35+
typedef void (*mysql_claim_t)(void *ptr);
3536
typedef void (*mysql_free_t)(void *ptr);
3637
typedef void * (*my_memdup_t)(PSI_memory_key key, const void *from, size_t length, myf_t flags);
3738
typedef char * (*my_strdup_t)(PSI_memory_key key, const char *from, myf_t flags);
@@ -41,6 +42,7 @@ struct mysql_malloc_service_st
4142
{
4243
mysql_malloc_t mysql_malloc;
4344
mysql_realloc_t mysql_realloc;
45+
mysql_claim_t mysql_claim;
4446
mysql_free_t mysql_free;
4547
my_memdup_t my_memdup;
4648
my_strdup_t my_strdup;
@@ -53,6 +55,7 @@ extern struct mysql_malloc_service_st *mysql_malloc_service;
5355

5456
#define my_malloc mysql_malloc_service->mysql_malloc
5557
#define my_realloc mysql_malloc_service->mysql_realloc
58+
#define my_claim mysql_malloc_service->mysql_claim
5659
#define my_free mysql_malloc_service->mysql_free
5760
#define my_memdup mysql_malloc_service->my_memdup
5861
#define my_strdup mysql_malloc_service->my_strdup
@@ -62,6 +65,7 @@ extern struct mysql_malloc_service_st *mysql_malloc_service;
6265

6366
extern void * my_malloc(PSI_memory_key key, size_t size, myf_t flags);
6467
extern void * my_realloc(PSI_memory_key key, void *ptr, size_t size, myf_t flags);
68+
extern void my_claim(void *ptr);
6569
extern void my_free(void *ptr);
6670
extern void * my_memdup(PSI_memory_key key, const void *from, size_t length, myf_t flags);
6771
extern char * my_strdup(PSI_memory_key key, const char *from, myf_t flags);

include/mysql/services.h.pp

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -106,10 +106,12 @@
106106
#include <mysql/service_mysql_alloc.h>
107107
#include "mysql/psi/psi_memory.h"
108108
#include "psi_base.h"
109+
struct PSI_thread;
109110
typedef unsigned int PSI_memory_key;
110111
typedef int myf_t;
111112
typedef void * (*mysql_malloc_t)(PSI_memory_key key, size_t size, myf_t flags);
112113
typedef void * (*mysql_realloc_t)(PSI_memory_key key, void *ptr, size_t size, myf_t flags);
114+
typedef void (*mysql_claim_t)(void *ptr);
113115
typedef void (*mysql_free_t)(void *ptr);
114116
typedef void * (*my_memdup_t)(PSI_memory_key key, const void *from, size_t length, myf_t flags);
115117
typedef char * (*my_strdup_t)(PSI_memory_key key, const char *from, myf_t flags);
@@ -118,6 +120,7 @@
118120
{
119121
mysql_malloc_t mysql_malloc;
120122
mysql_realloc_t mysql_realloc;
123+
mysql_claim_t mysql_claim;
121124
mysql_free_t mysql_free;
122125
my_memdup_t my_memdup;
123126
my_strdup_t my_strdup;
@@ -126,6 +129,7 @@
126129
extern struct mysql_malloc_service_st *mysql_malloc_service;
127130
extern void * my_malloc(PSI_memory_key key, size_t size, myf_t flags);
128131
extern void * my_realloc(PSI_memory_key key, void *ptr, size_t size, myf_t flags);
132+
extern void my_claim(void *ptr);
129133
extern void my_free(void *ptr);
130134
extern void * my_memdup(PSI_memory_key key, const void *from, size_t length, myf_t flags);
131135
extern char * my_strdup(PSI_memory_key key, const char *from, myf_t flags);

include/mysql_com.h

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -508,6 +508,7 @@ my_bool my_net_init(NET *net, Vio* vio);
508508
void my_net_local_init(NET *net);
509509
void net_end(NET *net);
510510
void net_clear(NET *net, my_bool check_buffer);
511+
void net_claim_memory_ownership(NET *net);
511512
my_bool net_realloc(NET *net, size_t length);
512513
my_bool net_flush(NET *net);
513514
my_bool my_net_write(NET *net,const unsigned char *packet, size_t len);

include/sql_string.h

Lines changed: 9 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -320,6 +320,14 @@ class String
320320
DBUG_ASSERT(strlen(m_ptr) == m_length);
321321
}
322322

323+
void mem_claim()
324+
{
325+
if (m_is_alloced)
326+
{
327+
my_claim(m_ptr);
328+
}
329+
}
330+
323331
void mem_free()
324332
{
325333
if (m_is_alloced)
@@ -331,6 +339,7 @@ class String
331339
m_length= 0; /* Safety */
332340
}
333341
}
342+
334343
bool alloc(size_t arg_length)
335344
{
336345
if (arg_length < m_alloced_length)

0 commit comments

Comments
 (0)