Description:
In the bug report mysqlbug14637(http://bugs.mysql.com/bug.php?id=14637), reporter finds that two functions, my_hash_sort_simple() and my_lengthsp_8bit(), trim blank spaces from the end of a string. These two functions parse the string byte wise and are quite slow for longer strings.
The reporter suggests a word wise way to parse the string, and the patch for this bug exactly does the same thing. Another important thing worth mentioning is that the patch employs a string length threshold, and only when the length of string is longer than 20, the patched function will use word-wise comparison. In my point of view, I think all skip_trailing_space operations should use this patch. After we have done this, we will get at least not worse performance, and in some situation we can get better performance.
In the bug report of mysqlbug60345 (http://bugs.mysql.com/bug.php?id=60345), I report some missing bug places in mysql-5.1.55 and mysql-6.0.11. Some of these places are fixed in mysql-6.0.11, and some of these places are not fixed in either of these two versions.
After checking other parts of codes, I find 12 places which can use the patch directly. I believe after we use the patch, we will not get worse performance, and in some situation, we will get better performance.
1 /mysql-5.1.55/cmd-line-utils/libedit/refresh.c:497
while (ofd < o) {
if (o[-1] != ' ')
break;
o--;
}
2 /mysql-5.1.55/storage/innobase/row/row0mysql.c:333
while (col_len > 0
&& ptr[col_len - 1] == 0x20) {
col_len--;}
3 /mysql-5.1.55/storage/innobase/row/row0mysql.c:372
while (col_len > 0
&& ptr[col_len - 1] == 0x20) {
col_len--;}
4 /mysql-5.1.55/storage/innodb_plugin/row/row0mysql.c:377
while (col_len > 0
&& ptr[col_len - 1] == 0x20) {
col_len--;}
5 /mysql-5.1.55/storage/innodb_plugin/row/row0mysql.c:416
while (col_len > n_chars && ptr[col_len - 1] == 0x20) {
col_len--;}
6 /mysql-5.1.55/storage/myisam/mi_key.c:264
while (end > pos && end[-1] == ' ')
end--;
7 /mysql-5.1.55/storage/myisam/mi_dynrec.c:1153
while (end > record && *(end-1) == ' ')
end--;
8 /mysql-5.1.55/storage/myisam/mi_dynrec.c:1033
while (end > from && *(end-1) == ' ')
end--;
9 /mysql-5.1.55/storage/myisam/myisampack.c:2538
for (pos=end_pos ; pos > start_pos && pos[-1] == ' ' ; pos--) ;
10 /mysql-5.1.55/sql/field.cc:6904
while (end > ptr && end[-1] == ' ')
end--;
11 /mysql-5.1.55/sql/mysqld.cc:9081
while (end > pos && end[-1] == ' ')
end--;
12 /mysql-5.1.55/sql/sql_select.cc:14484
for (str=copy->str,end= str+copy->length;
end > str && end[-1] == ' ' ;
end--) ;
How to repeat:
code review
Suggested fix:
use the patch of mysql14637
static inline const uchar *skip_trailing_space(const uchar *ptr,size_t len)
{
const uchar *end= ptr + len;
if (len > 20)
{
const uchar *end_words= (const uchar *)(intptr)
(((ulonglong)(intptr)end) / SIZEOF_INT * SIZEOF_INT);
const uchar *start_words= (const uchar *)(intptr)
((((ulonglong)(intptr)ptr) + SIZEOF_INT - 1) / SIZEOF_INT * SIZEOF_INT);
DBUG_ASSERT(((ulonglong)(intptr)ptr) >= SIZEOF_INT);
if (end_words > ptr)
{
while (end > end_words && end[-1] == 0x20)
end--;
if (end[-1] == 0x20 && start_words < end_words)
while (end > start_words && ((unsigned *)end)[-1] == SPACE_INT)
end -= SIZEOF_INT;
}
}
while (end > ptr && end[-1] == 0x20)
end--;
return (end);
}