Skip to content

Commit 1e139ad

Browse files
author
Tor Didriksen
committed
Bug#21866029 HEAP ENGINE WASTES CPU RE-CALCULATING HASH VALUES
Problem: my_hash_sort_simple consumes lots of CPU Solution: cache computed hash values
1 parent ee5a494 commit 1e139ad

File tree

6 files changed

+43
-34
lines changed

6 files changed

+43
-34
lines changed

storage/heap/_check.c

Lines changed: 3 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,4 @@
1-
/* Copyright (c) 2000, 2002-2007 MySQL AB
2-
Use is subject to license terms
1+
/* Copyright (c) 2000, 2015, Oracle and/or its affiliates. All rights reserved.
32
43
This program is free software; you can redistribute it and/or modify
54
it under the terms of the GNU General Public License as published by
@@ -111,18 +110,15 @@ static int check_one_key(HP_KEYDEF *keydef, uint keynr, ulong records,
111110
for (i=found=max_links=seek=0 ; i < records ; i++)
112111
{
113112
hash_info=hp_find_hash(&keydef->block,i);
114-
if (hp_mask(hp_rec_hashnr(keydef, hash_info->ptr_to_rec),
115-
blength,records) == i)
113+
if (hp_mask(hash_info->hash, blength,records) == i)
116114
{
117115
found++;
118116
seek++;
119117
links=1;
120118
while ((hash_info=hash_info->next_key) && found < records + 1)
121119
{
122120
seek+= ++links;
123-
if ((rec_link = hp_mask(hp_rec_hashnr(keydef, hash_info->ptr_to_rec),
124-
blength, records))
125-
!= i)
121+
if (i != (rec_link= hp_mask(hash_info->hash, blength, records)))
126122
{
127123
DBUG_PRINT("error",
128124
("Record in wrong link: Link %lu Record: 0x%lx Record-link %lu",

storage/heap/ha_heap.cc

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -680,7 +680,7 @@ heap_prepare_hp_create_info(TABLE *table_arg, bool internal_table,
680680
case HA_KEY_ALG_UNDEF:
681681
case HA_KEY_ALG_HASH:
682682
keydef[key].algorithm= HA_KEY_ALG_HASH;
683-
mem_per_row+= sizeof(char*) * 2; // = sizeof(HASH_INFO)
683+
mem_per_row+= sizeof(HASH_INFO);
684684
break;
685685
case HA_KEY_ALG_BTREE:
686686
keydef[key].algorithm= HA_KEY_ALG_BTREE;

storage/heap/heapdef.h

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -51,6 +51,7 @@ typedef struct st_hp_hash_info
5151
{
5252
struct st_hp_hash_info *next_key;
5353
uchar *ptr_to_rec;
54+
ulong hash; /* Cached key hash value. */
5455
} HASH_INFO;
5556

5657
typedef struct {

storage/heap/hp_delete.c

Lines changed: 3 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -149,8 +149,7 @@ int hp_delete_key(HP_INFO *info, HP_KEYDEF *keyinfo,
149149
else if (pos->next_key)
150150
{
151151
empty=pos->next_key;
152-
pos->ptr_to_rec=empty->ptr_to_rec;
153-
pos->next_key=empty->next_key;
152+
*pos= *empty;
154153
}
155154
else
156155
keyinfo->hash_buckets--;
@@ -159,7 +158,7 @@ int hp_delete_key(HP_INFO *info, HP_KEYDEF *keyinfo,
159158
DBUG_RETURN (0);
160159

161160
/* Move the last key (lastpos) */
162-
lastpos_hashnr = hp_rec_hashnr(keyinfo, lastpos->ptr_to_rec);
161+
lastpos_hashnr= lastpos->hash;
163162
/* pos is where lastpos should be */
164163
pos=hp_find_hash(&keyinfo->block, hp_mask(lastpos_hashnr, share->blength,
165164
share->records));
@@ -168,7 +167,7 @@ int hp_delete_key(HP_INFO *info, HP_KEYDEF *keyinfo,
168167
empty[0]=lastpos[0];
169168
DBUG_RETURN(0);
170169
}
171-
pos_hashnr = hp_rec_hashnr(keyinfo, pos->ptr_to_rec);
170+
pos_hashnr= pos->hash;
172171
/* pos3 is where the pos should be */
173172
pos3= hp_find_hash(&keyinfo->block,
174173
hp_mask(pos_hashnr, share->blength, share->records));

storage/heap/hp_test2.c

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -64,7 +64,7 @@ int main(int argc, char *argv[])
6464
get_options(argc,argv);
6565

6666
memset(&hp_create_info, 0, sizeof(hp_create_info));
67-
hp_create_info.max_table_size= 1024L*1024L;
67+
hp_create_info.max_table_size= 1024L * 1024L * 2;
6868
hp_create_info.keys= keys;
6969
hp_create_info.keydef= keyinfo;
7070
hp_create_info.reclength= reclength;

storage/heap/hp_write.c

Lines changed: 34 additions & 21 deletions
Original file line numberDiff line numberDiff line change
@@ -166,6 +166,24 @@ static uchar *next_free_record_pos(HP_SHARE *info)
166166
}
167167

168168

169+
/**
170+
Populate HASH_INFO structure.
171+
172+
@param key Pointer to a HASH_INFO key to be populated
173+
@param next_key HASH_INFO next_key value
174+
@param ptr_to_rec HASH_INFO ptr_to_rec value
175+
@param hash HASH_INFO hash value
176+
*/
177+
178+
static inline void set_hash_key(HASH_INFO *key, HASH_INFO *next_key,
179+
uchar *ptr_to_rec, ulong hash)
180+
{
181+
key->next_key= next_key;
182+
key->ptr_to_rec= ptr_to_rec;
183+
key->hash= hash;
184+
}
185+
186+
169187
/*
170188
Write a hash-key to the hash-index
171189
SYNOPSIS
@@ -198,6 +216,7 @@ int hp_write_key(HP_INFO *info, HP_KEYDEF *keyinfo,
198216
int flag;
199217
ulong halfbuff,hashnr,first_index;
200218
uchar *ptr_to_rec= NULL, *ptr_to_rec2= NULL;
219+
ulong hash1= 0, hash2= 0;
201220
HASH_INFO *empty, *gpos= NULL, *gpos2= NULL, *pos;
202221
DBUG_ENTER("hp_write_key");
203222

@@ -227,7 +246,7 @@ int hp_write_key(HP_INFO *info, HP_KEYDEF *keyinfo,
227246
{
228247
do
229248
{
230-
hashnr = hp_rec_hashnr(keyinfo, pos->ptr_to_rec);
249+
hashnr= pos->hash;
231250
if (flag == 0)
232251
{
233252
/*
@@ -279,13 +298,13 @@ int hp_write_key(HP_INFO *info, HP_KEYDEF *keyinfo,
279298
if (!(flag & LOWUSED))
280299
{
281300
/* Change link of previous lower-list key */
282-
gpos->ptr_to_rec=ptr_to_rec;
283-
gpos->next_key=pos;
301+
set_hash_key(gpos, pos, ptr_to_rec, hash1);
284302
flag= (flag & HIGHFIND) | (LOWFIND | LOWUSED);
285303
}
286304
gpos=pos;
287305
ptr_to_rec=pos->ptr_to_rec;
288306
}
307+
hash1= pos->hash;
289308
}
290309
else
291310
{
@@ -303,13 +322,13 @@ int hp_write_key(HP_INFO *info, HP_KEYDEF *keyinfo,
303322
if (!(flag & HIGHUSED))
304323
{
305324
/* Change link of previous upper-list key and save */
306-
gpos2->ptr_to_rec=ptr_to_rec2;
307-
gpos2->next_key=pos;
325+
set_hash_key(gpos2, pos, ptr_to_rec2, hash2);
308326
flag= (flag & LOWFIND) | (HIGHFIND | HIGHUSED);
309327
}
310328
gpos2=pos;
311329
ptr_to_rec2=pos->ptr_to_rec;
312330
}
331+
hash2= pos->hash;
313332
}
314333
}
315334
while ((pos=pos->next_key));
@@ -325,42 +344,36 @@ int hp_write_key(HP_INFO *info, HP_KEYDEF *keyinfo,
325344

326345
if ((flag & (LOWFIND | LOWUSED)) == LOWFIND)
327346
{
328-
gpos->ptr_to_rec=ptr_to_rec;
329-
gpos->next_key=0;
347+
set_hash_key(gpos, NULL, ptr_to_rec, hash1);
330348
}
331349
if ((flag & (HIGHFIND | HIGHUSED)) == HIGHFIND)
332350
{
333-
gpos2->ptr_to_rec=ptr_to_rec2;
334-
gpos2->next_key=0;
351+
set_hash_key(gpos2, NULL, ptr_to_rec2, hash2);
335352
}
336353
}
337354
/* Check if we are at the empty position */
338-
339-
pos=hp_find_hash(&keyinfo->block, hp_mask(hp_rec_hashnr(keyinfo, record),
340-
share->blength, share->records + 1));
355+
hash1= hp_rec_hashnr(keyinfo, record);
356+
pos= hp_find_hash(&keyinfo->block, hp_mask(hash1, share->blength,
357+
share->records + 1));
341358
if (pos == empty)
342359
{
343-
pos->ptr_to_rec=recpos;
344-
pos->next_key=0;
360+
set_hash_key(pos, NULL, recpos, hash1);
345361
keyinfo->hash_buckets++;
346362
}
347363
else
348364
{
349365
/* Check if more records in same hash-nr family */
350366
empty[0]=pos[0];
351-
gpos=hp_find_hash(&keyinfo->block,
352-
hp_mask(hp_rec_hashnr(keyinfo, pos->ptr_to_rec),
353-
share->blength, share->records + 1));
367+
gpos= hp_find_hash(&keyinfo->block, hp_mask(pos->hash, share->blength,
368+
share->records + 1));
354369
if (pos == gpos)
355370
{
356-
pos->ptr_to_rec=recpos;
357-
pos->next_key=empty;
371+
set_hash_key(pos, empty, recpos, hash1);
358372
}
359373
else
360374
{
375+
set_hash_key(pos, NULL, recpos, hash1);
361376
keyinfo->hash_buckets++;
362-
pos->ptr_to_rec=recpos;
363-
pos->next_key=0;
364377
hp_movelink(pos, gpos, empty);
365378
}
366379

0 commit comments

Comments
 (0)