Merge lp:~vlad-lesin/percona-server/5.1-gca-bug-1038940-table_cache_speed_up into lp:percona-server/5.1

Proposed by Vlad Lesin
Status: Work in progress
Proposed branch: lp:~vlad-lesin/percona-server/5.1-gca-bug-1038940-table_cache_speed_up
Merge into: lp:percona-server/5.1
Diff against target: 441 lines (+185/-99)
10 files modified
Percona-Server/storage/myisam/ha_myisam.cc (+4/-0)
Percona-Server/storage/myisam/mi_close.c (+1/-1)
Percona-Server/storage/myisam/mi_dbug.c (+3/-3)
Percona-Server/storage/myisam/mi_keycache.c (+3/-3)
Percona-Server/storage/myisam/mi_open.c (+67/-13)
Percona-Server/storage/myisam/mi_panic.c (+92/-75)
Percona-Server/storage/myisam/mi_static.c (+1/-1)
Percona-Server/storage/myisam/myisamchk.c (+6/-0)
Percona-Server/storage/myisam/myisamdef.h (+3/-3)
Percona-Server/storage/myisam/myisampack.c (+5/-0)
To merge this branch: bzr merge lp:~vlad-lesin/percona-server/5.1-gca-bug-1038940-table_cache_speed_up
Reviewer Review Type Date Requested Status
Laurynas Biveinis (community) Needs Fixing
Stewart Smith Pending
Review via email: mp+141711@code.launchpad.net

Description of the change

This MP is port of this http://lists.mysql.com/commits/121507 patch to 5.1(see issue #25137). The main idea of this patch is to replace linked list of opened tables with hash-table to improve performance of open table lookup mechanism.

Jenkins test:
http://jenkins.percona.com/view/PS%205.1/job/percona-server-5.1-param/480

This is just copy of this https://code.launchpad.net/~vlad-lesin/percona-server/5.1-table_cache_speed_up/+merge/120285 MP to 5.1 GCA clone to make merging to 5.5 easier.

To post a comment you must log in.
Revision history for this message
Vlad Lesin (vlad-lesin) wrote :
Revision history for this message
Laurynas Biveinis (laurynas-biveinis) :
review: Approve
Revision history for this message
Stewart Smith (stewart) wrote :

FYI since the 5.5 MP is Work In Progress, I can't yet merge the 5.1 one either.

Revision history for this message
Vlad Lesin (vlad-lesin) wrote :

Unnecessary changes from mi_panic.c are removed.

Revision history for this message
Vlad Lesin (vlad-lesin) wrote :
Revision history for this message
Laurynas Biveinis (laurynas-biveinis) wrote :

The patch is OK, but I'll have to ask you to redo it as a GCA involving all three 5.1/5.5/5.6.

review: Needs Fixing

Unmerged revisions

510. By Vlad Lesin

Fix for bug #1038940.

As the number of open tables is increased, table lookup
(testing if a table is already open) and (in particular)
the case when a table is not open, became increasingly more
expensive.

The problem was caused by the open table lookup mechanism,
which was based on traversing a linked list comparing the
file names.

As the list was replaced by a hash table, the lookup
time dropped significantly when used on systems with
a large number of open tables.

The original patch can be found here:
http://lists.mysql.com/commits/121507

Preview Diff

[H/L] Next/Prev Comment, [J/K] Next/Prev File, [N/P] Next/Prev Hunk
=== modified file 'Percona-Server/storage/myisam/ha_myisam.cc'
--- Percona-Server/storage/myisam/ha_myisam.cc 2011-11-24 16:33:30 +0000
+++ Percona-Server/storage/myisam/ha_myisam.cc 2013-01-03 08:27:23 +0000
@@ -2201,6 +2201,10 @@
2201 myisam_hton->create= myisam_create_handler;2201 myisam_hton->create= myisam_create_handler;
2202 myisam_hton->panic= myisam_panic;2202 myisam_hton->panic= myisam_panic;
2203 myisam_hton->flags= HTON_CAN_RECREATE | HTON_SUPPORT_LOG_TABLES;2203 myisam_hton->flags= HTON_CAN_RECREATE | HTON_SUPPORT_LOG_TABLES;
2204
2205 if (mi_init_open_table_hash(table_cache_size))
2206 return 1;
2207
2204 return 0;2208 return 0;
2205}2209}
22062210
22072211
=== modified file 'Percona-Server/storage/myisam/mi_close.c'
--- Percona-Server/storage/myisam/mi_close.c 2012-02-15 16:21:38 +0000
+++ Percona-Server/storage/myisam/mi_close.c 2013-01-03 08:27:23 +0000
@@ -56,7 +56,7 @@
56 info->opt_flag&= ~(READ_CACHE_USED | WRITE_CACHE_USED);56 info->opt_flag&= ~(READ_CACHE_USED | WRITE_CACHE_USED);
57 }57 }
58 flag= !--share->reopen;58 flag= !--share->reopen;
59 myisam_open_list=list_delete(myisam_open_list,&info->open_list);59 my_hash_delete(&myisam_open_table_hash, (uchar *) info);
60 pthread_mutex_unlock(&share->intern_lock);60 pthread_mutex_unlock(&share->intern_lock);
6161
62 my_free(mi_get_rec_buff_ptr(info, info->rec_buff), MYF(MY_ALLOW_ZERO_PTR));62 my_free(mi_get_rec_buff_ptr(info, info->rec_buff), MYF(MY_ALLOW_ZERO_PTR));
6363
=== modified file 'Percona-Server/storage/myisam/mi_dbug.c'
--- Percona-Server/storage/myisam/mi_dbug.c 2011-06-30 15:37:13 +0000
+++ Percona-Server/storage/myisam/mi_dbug.c 2013-01-03 08:27:23 +0000
@@ -172,13 +172,13 @@
172my_bool check_table_is_closed(const char *name, const char *where)172my_bool check_table_is_closed(const char *name, const char *where)
173{173{
174 char filename[FN_REFLEN];174 char filename[FN_REFLEN];
175 LIST *pos;175 uint idx;
176 DBUG_ENTER("check_table_is_closed");176 DBUG_ENTER("check_table_is_closed");
177177
178 (void) fn_format(filename,name,"",MI_NAME_IEXT,4+16+32);178 (void) fn_format(filename,name,"",MI_NAME_IEXT,4+16+32);
179 for (pos=myisam_open_list ; pos ; pos=pos->next)179 for (idx= 0; idx < myisam_open_table_hash.records; ++idx)
180 {180 {
181 MI_INFO *info=(MI_INFO*) pos->data;181 MI_INFO *info=(MI_INFO*) my_hash_element(&myisam_open_table_hash, idx);
182 MYISAM_SHARE *share=info->s;182 MYISAM_SHARE *share=info->s;
183 if (!strcmp(share->unique_file_name,filename))183 if (!strcmp(share->unique_file_name,filename))
184 {184 {
185185
=== modified file 'Percona-Server/storage/myisam/mi_keycache.c'
--- Percona-Server/storage/myisam/mi_keycache.c 2008-03-29 15:56:33 +0000
+++ Percona-Server/storage/myisam/mi_keycache.c 2013-01-03 08:27:23 +0000
@@ -137,16 +137,16 @@
137void mi_change_key_cache(KEY_CACHE *old_key_cache,137void mi_change_key_cache(KEY_CACHE *old_key_cache,
138 KEY_CACHE *new_key_cache)138 KEY_CACHE *new_key_cache)
139{139{
140 LIST *pos;140 uint idx;
141 DBUG_ENTER("mi_change_key_cache");141 DBUG_ENTER("mi_change_key_cache");
142142
143 /*143 /*
144 Lock list to ensure that no one can close the table while we manipulate it144 Lock list to ensure that no one can close the table while we manipulate it
145 */145 */
146 pthread_mutex_lock(&THR_LOCK_myisam);146 pthread_mutex_lock(&THR_LOCK_myisam);
147 for (pos=myisam_open_list ; pos ; pos=pos->next)147 for (idx= 0; idx < myisam_open_table_hash.records; ++idx)
148 {148 {
149 MI_INFO *info= (MI_INFO*) pos->data;149 MI_INFO *info=(MI_INFO*) my_hash_element(&myisam_open_table_hash, idx);
150 MYISAM_SHARE *share= info->s;150 MYISAM_SHARE *share= info->s;
151 if (share->key_cache == old_key_cache)151 if (share->key_cache == old_key_cache)
152 mi_assign_to_key_cache(info, (ulonglong) ~0, new_key_cache);152 mi_assign_to_key_cache(info, (ulonglong) ~0, new_key_cache);
153153
=== modified file 'Percona-Server/storage/myisam/mi_open.c'
--- Percona-Server/storage/myisam/mi_open.c 2011-06-30 15:37:13 +0000
+++ Percona-Server/storage/myisam/mi_open.c 2013-01-03 08:27:23 +0000
@@ -46,23 +46,76 @@
46}46}
4747
4848
49/******************************************************************************49/*
50** Return the shared struct if the table is already open.50 Get the value used as hash key (helper function for the
51** In MySQL the server will handle version issues.51 open table hash). Function is used as a callback
52******************************************************************************/52 from the hash table
5353*/
54static uchar *mi_open_table_hash_key(const uchar *record, size_t *length,
55 my_bool not_used __attribute__((unused)))
56{
57 MI_INFO *info= (MI_INFO *) record;
58 *length= info->s->unique_name_length;
59 return (uchar*) info->s->unique_file_name;
60}
61
62/**
63 Initialize open table hash
64
65 Function is normally called from myisam_init
66 with the system variable table_cache_size used
67 as hash_size.
68
69 @param[in] hash_size Initial has size (elements)
70 @return inidicates success or failure of initialization
71 @retval 0 success
72 @retval 1 failure
73
74*/
75int mi_init_open_table_hash(ulong hash_size)
76{
77 if (hash_size == 0)
78 hash_size= 32; /* default hash size */
79
80 if (my_hash_init(&myisam_open_table_hash, &my_charset_filename,
81 hash_size, 0, 0, mi_open_table_hash_key, 0, 0))
82 return 1; /* error */
83
84 return 0;
85}
86
87
88/**
89 Retrieve the shared struct if the table is already
90 open (i.e in the open table hash)
91
92 @param[in] filename table file name
93 @return shared struct, 0 if not in the cache
94*/
54MI_INFO *test_if_reopen(char *filename)95MI_INFO *test_if_reopen(char *filename)
55{96{
56 LIST *pos;97 HASH_SEARCH_STATE current_record;
98 int len= strlen(filename);
5799
58 for (pos=myisam_open_list ; pos ; pos=pos->next)100 MI_INFO *info= (MI_INFO*) my_hash_first(&myisam_open_table_hash,
101 (uchar *) filename,
102 len, &current_record);
103 /*
104 There might be more than one instance of a table share for
105 a given table in the hash table. We're interested in the one with
106 last_version set, so we iterate until we find it
107 */
108 while (info)
59 {109 {
60 MI_INFO *info=(MI_INFO*) pos->data;
61 MYISAM_SHARE *share=info->s;110 MYISAM_SHARE *share=info->s;
62 if (!strcmp(share->unique_file_name,filename) && share->last_version)111 if (share->last_version)
63 return info;112 break;
113
114 info= (MI_INFO*) my_hash_next(&myisam_open_table_hash,
115 (uchar *) filename,
116 len, &current_record);
64 }117 }
65 return 0;118 return info;
66}119}
67120
68121
@@ -650,8 +703,9 @@
650#ifdef THREAD703#ifdef THREAD
651 thr_lock_data_init(&share->lock,&m_info->lock,(void*) m_info);704 thr_lock_data_init(&share->lock,&m_info->lock,(void*) m_info);
652#endif705#endif
653 m_info->open_list.data=(void*) m_info;706
654 myisam_open_list=list_add(myisam_open_list,&m_info->open_list);707 if (my_hash_insert(&myisam_open_table_hash, (uchar *) m_info))
708 goto err;
655709
656 pthread_mutex_unlock(&THR_LOCK_myisam);710 pthread_mutex_unlock(&THR_LOCK_myisam);
657711
658712
=== modified file 'Percona-Server/storage/myisam/mi_panic.c'
--- Percona-Server/storage/myisam/mi_panic.c 2006-12-31 00:32:21 +0000
+++ Percona-Server/storage/myisam/mi_panic.c 2013-01-03 08:27:23 +0000
@@ -26,85 +26,102 @@
26int mi_panic(enum ha_panic_function flag)26int mi_panic(enum ha_panic_function flag)
27{27{
28 int error=0;28 int error=0;
29 LIST *list_element,*next_open;
30 MI_INFO *info;29 MI_INFO *info;
30 uint idx;
31 DBUG_ENTER("mi_panic");31 DBUG_ENTER("mi_panic");
3232
33 pthread_mutex_lock(&THR_LOCK_myisam);33 pthread_mutex_lock(&THR_LOCK_myisam);
34 for (list_element=myisam_open_list ; list_element ; list_element=next_open)34 if (my_hash_inited(&myisam_open_table_hash))
35 {35 {
36 next_open=list_element->next; /* Save if close */36 if (flag == HA_PANIC_CLOSE)
37 info=(MI_INFO*) list_element->data;37 {
38 switch (flag) {38 while (myisam_open_table_hash.records)
39 case HA_PANIC_CLOSE:39 {
40 pthread_mutex_unlock(&THR_LOCK_myisam); /* Not exactly right... */40 /*
41 if (mi_close(info))41 As long as there are records in the hash, fetch the
42 error=my_errno;42 first, and close it.
43 pthread_mutex_lock(&THR_LOCK_myisam);43 */
44 break;44 info=(MI_INFO*) my_hash_element(&myisam_open_table_hash, 0);
45 case HA_PANIC_WRITE: /* Do this to free databases */45 pthread_mutex_unlock(&THR_LOCK_myisam); /* Not exactly right... */
46#ifdef CANT_OPEN_FILES_TWICE46 if (mi_close(info))
47 if (info->s->options & HA_OPTION_READ_ONLY_DATA)47 error= my_errno;
48 break;48 pthread_mutex_lock(&THR_LOCK_myisam);
49#endif49 }
50 if (flush_key_blocks(info->s->key_cache, info->s->kfile, FLUSH_RELEASE))50 (void) mi_log(0); /* Close log if neaded */
51 error=my_errno;51 ft_free_stopwords();
52 if (info->opt_flag & WRITE_CACHE_USED)52 }
53 if (flush_io_cache(&info->rec_cache))53 else
54 error=my_errno;54 {
55 if (info->opt_flag & READ_CACHE_USED)55 for (idx= 0; idx < myisam_open_table_hash.records; ++idx)
56 {56 {
57 if (flush_io_cache(&info->rec_cache))57 info=(MI_INFO*) my_hash_element(&myisam_open_table_hash, idx);
58 error=my_errno;58 switch (flag) {
59 reinit_io_cache(&info->rec_cache,READ_CACHE,0,59 case HA_PANIC_CLOSE: break; /* To eliminate warning. Handled above */
60 (pbool) (info->lock_type != F_UNLCK),1);60 case HA_PANIC_WRITE: /* Do this to free databases */
61 }61
62 if (info->lock_type != F_UNLCK && ! info->was_locked)62#ifdef CANT_OPEN_FILES_TWICE
63 {63 if (info->s->options & HA_OPTION_READ_ONLY_DATA)
64 info->was_locked=info->lock_type;64 break;
65 if (mi_lock_database(info,F_UNLCK))65#endif
66 error=my_errno;66 if (flush_key_blocks(info->s->key_cache, info->s->kfile, FLUSH_RELEASE))
67 }67 error=my_errno;
68#ifdef CANT_OPEN_FILES_TWICE68 if (info->opt_flag & WRITE_CACHE_USED)
69 if (info->s->kfile >= 0 && my_close(info->s->kfile,MYF(0)))69 if (flush_io_cache(&info->rec_cache))
70 error = my_errno;70 error=my_errno;
71 if (info->dfile >= 0 && my_close(info->dfile,MYF(0)))71 if (info->opt_flag & READ_CACHE_USED)
72 error = my_errno;72 {
73 info->s->kfile=info->dfile= -1; /* Files aren't open anymore */73 if (flush_io_cache(&info->rec_cache))
74 break;74 error=my_errno;
75#endif75 reinit_io_cache(&info->rec_cache,READ_CACHE,0,
76 case HA_PANIC_READ: /* Restore to before WRITE */76 (pbool) (info->lock_type != F_UNLCK),1);
77#ifdef CANT_OPEN_FILES_TWICE77 }
78 { /* Open closed files */78 if (info->lock_type != F_UNLCK && ! info->was_locked)
79 char name_buff[FN_REFLEN];79 {
80 if (info->s->kfile < 0)80 info->was_locked=info->lock_type;
81 if ((info->s->kfile= my_open(fn_format(name_buff,info->filename,"",81 if (mi_lock_database(info,F_UNLCK))
82 N_NAME_IEXT,4),info->mode,82 error=my_errno;
83 MYF(MY_WME))) < 0)83 }
84 error = my_errno;84#ifdef CANT_OPEN_FILES_TWICE
85 if (info->dfile < 0)85 if (info->s->kfile >= 0 && mysql_file_close(info->s->kfile, MYF(0)))
86 {86 error = my_errno;
87 if ((info->dfile= my_open(fn_format(name_buff,info->filename,"",87 if (info->dfile >= 0 && mysql_file_close(info->dfile, MYF(0)))
88 N_NAME_DEXT,4),info->mode,88 error = my_errno;
89 MYF(MY_WME))) < 0)89 info->s->kfile=info->dfile= -1; /* Files aren't open anymore */
90 error = my_errno;90 break;
91 info->rec_cache.file=info->dfile;91#endif
92 }92 case HA_PANIC_READ: /* Restore to before WRITE */
93 }93#ifdef CANT_OPEN_FILES_TWICE
94#endif94 { /* Open closed files */
95 if (info->was_locked)95 char name_buff[FN_REFLEN];
96 {96 if (info->s->kfile < 0)
97 if (mi_lock_database(info, info->was_locked))97 if ((info->s->kfile= mysql_file_open(mi_key_file_kfile,
98 error=my_errno;98 fn_format(name_buff,
99 info->was_locked=0;99 info->filename, "",
100 }100 N_NAME_IEXT, 4),
101 break;101 info->mode, MYF(MY_WME))) < 0)
102 }102 error = my_errno;
103 }103 if (info->dfile < 0)
104 if (flag == HA_PANIC_CLOSE)104 {
105 {105 if ((info->dfile= mysql_file_open(mi_key_file_dfile,
106 VOID(mi_log(0)); /* Close log if neaded */106 fn_format(name_buff,
107 ft_free_stopwords();107 info->filename, "",
108 N_NAME_DEXT, 4),
109 info->mode, MYF(MY_WME))) < 0)
110 error = my_errno;
111 info->rec_cache.file=info->dfile;
112 }
113 }
114#endif
115 if (info->was_locked)
116 {
117 if (mi_lock_database(info, info->was_locked))
118 error=my_errno;
119 info->was_locked=0;
120 }
121 break;
122 }
123 }
124 }
108 }125 }
109 pthread_mutex_unlock(&THR_LOCK_myisam);126 pthread_mutex_unlock(&THR_LOCK_myisam);
110 if (!error)127 if (!error)
111128
=== modified file 'Percona-Server/storage/myisam/mi_static.c'
--- Percona-Server/storage/myisam/mi_static.c 2011-06-30 15:37:13 +0000
+++ Percona-Server/storage/myisam/mi_static.c 2013-01-03 08:27:23 +0000
@@ -25,7 +25,7 @@
25#include "myisamdef.h"25#include "myisamdef.h"
26#endif26#endif
2727
28LIST *myisam_open_list=0;28HASH myisam_open_table_hash;
29uchar NEAR myisam_file_magic[]=29uchar NEAR myisam_file_magic[]=
30{ (uchar) 254, (uchar) 254,'\007', '\001', };30{ (uchar) 254, (uchar) 254,'\007', '\001', };
31uchar NEAR myisam_pack_file_magic[]=31uchar NEAR myisam_pack_file_magic[]=
3232
=== modified file 'Percona-Server/storage/myisam/myisamchk.c'
--- Percona-Server/storage/myisam/myisamchk.c 2011-06-30 15:37:13 +0000
+++ Percona-Server/storage/myisam/myisamchk.c 2013-01-03 08:27:23 +0000
@@ -96,6 +96,12 @@
96 get_options(&argc,(char***) &argv);96 get_options(&argc,(char***) &argv);
97 myisam_quick_table_bits=decode_bits;97 myisam_quick_table_bits=decode_bits;
98 error=0;98 error=0;
99 if (mi_init_open_table_hash(0))
100 {
101 fprintf(stderr, "Can't initialize MyISAM storage engine\n");
102 exit(-1);
103 }
104
99 while (--argc >= 0)105 while (--argc >= 0)
100 {106 {
101 int new_error=myisamchk(&check_param, *(argv++));107 int new_error=myisamchk(&check_param, *(argv++));
102108
=== modified file 'Percona-Server/storage/myisam/myisamdef.h'
--- Percona-Server/storage/myisam/myisamdef.h 2011-11-24 02:01:56 +0000
+++ Percona-Server/storage/myisam/myisamdef.h 2013-01-03 08:27:23 +0000
@@ -26,6 +26,7 @@
26#else26#else
27#include <my_no_pthread.h>27#include <my_no_pthread.h>
28#endif28#endif
29#include "hash.h"
2930
30#if defined(my_write) && !defined(MAP_TO_USE_RAID)31#if defined(my_write) && !defined(MAP_TO_USE_RAID)
31#undef my_write /* undef map from my_nosys; We need test-if-disk full */32#undef my_write /* undef map from my_nosys; We need test-if-disk full */
@@ -286,7 +287,6 @@
286 uint data_changed; /* Somebody has changed data */287 uint data_changed; /* Somebody has changed data */
287 uint save_update; /* When using KEY_READ */288 uint save_update; /* When using KEY_READ */
288 int save_lastinx;289 int save_lastinx;
289 LIST open_list;
290 IO_CACHE rec_cache; /* When cacheing records */290 IO_CACHE rec_cache; /* When cacheing records */
291 uint preload_buff_size; /* When preloading indexes */291 uint preload_buff_size; /* When preloading indexes */
292 myf lock_wait; /* is 0 or MY_DONT_WAIT */292 myf lock_wait; /* is 0 or MY_DONT_WAIT */
@@ -472,8 +472,7 @@
472#endif472#endif
473473
474 /* Some extern variables */474 /* Some extern variables */
475475extern HASH myisam_open_table_hash;
476extern LIST *myisam_open_list;
477extern uchar NEAR myisam_file_magic[],NEAR myisam_pack_file_magic[];476extern uchar NEAR myisam_file_magic[],NEAR myisam_pack_file_magic[];
478extern uint NEAR myisam_read_vec[],NEAR myisam_readnext_vec[];477extern uint NEAR myisam_read_vec[],NEAR myisam_readnext_vec[];
479extern uint myisam_quick_table_bits;478extern uint myisam_quick_table_bits;
@@ -759,6 +758,7 @@
759void mi_disable_non_unique_index(MI_INFO *info, ha_rows rows);758void mi_disable_non_unique_index(MI_INFO *info, ha_rows rows);
760759
761extern MI_INFO *test_if_reopen(char *filename);760extern MI_INFO *test_if_reopen(char *filename);
761extern int mi_init_open_table_hash(ulong size);
762my_bool check_table_is_closed(const char *name, const char *where);762my_bool check_table_is_closed(const char *name, const char *where);
763int mi_open_datafile(MI_INFO *info, MYISAM_SHARE *share, const char *orn_name,763int mi_open_datafile(MI_INFO *info, MYISAM_SHARE *share, const char *orn_name,
764 File file_to_dup);764 File file_to_dup);
765765
=== modified file 'Percona-Server/storage/myisam/myisampack.c'
--- Percona-Server/storage/myisam/myisampack.c 2011-06-30 15:37:13 +0000
+++ Percona-Server/storage/myisam/myisampack.c 2013-01-03 08:27:23 +0000
@@ -210,6 +210,11 @@
210 MY_INIT(argv[0]);210 MY_INIT(argv[0]);
211211
212 load_defaults("my",load_default_groups,&argc,&argv);212 load_defaults("my",load_default_groups,&argc,&argv);
213 if (mi_init_open_table_hash(0))
214 {
215 fputs("Can't initialize MyISAM storage engine", stderr);
216 exit(1);
217 }
213 default_argv= argv;218 default_argv= argv;
214 get_options(&argc,&argv);219 get_options(&argc,&argv);
215220

Subscribers

People subscribed via source and target branches