Bug #60199 unnecessary string length computing for my_ismbchar()
Submitted: 22 Feb 2011 8:50 Modified: 18 Jan 2018 13:17
Reporter: Guoliang Jin Email Updates:
Status: Won't fix Impact on me:
None 
Category:MySQL Server: Charsets Severity:S5 (Performance)
Version:5.1.55, 5.1.62 OS:Any
Assigned to: CPU Architecture:Any

[22 Feb 2011 8:50] Guoliang Jin
Description:
While studying bug 15811, I found several cases may be handled similarly:

1. mysql-5.0.91/sql/item_func.cc:2668:    register uint32 n=0, l=my_ismbchar(res->charset(),str,str+res->length());

2. mysql-5.0.91/sql/item_strfunc.cc:767:      if ((l= my_ismbchar(res->charset(),ptr,end)))
other uses of "end" can also be eliminated

3. mysql-5.0.91/sql/item_strfunc.cc:881:        if ((l=my_ismbchar(res->charset(), ptr,strend))) ptr+=l;
the other use of "strend" can also be eliminated since the use of "end" can also be eliminated

4. mysql-5.0.91/sql/sql_parse.cc:6683:        (l = my_ismbchar(system_charset_info, name, strend)))
"strend" is calculated by "char *strend=name+(uint) strlen(name);" and not used elsewhere

5. mysql-5.0.91/client/mysql.cc:2035:        (length= my_ismbchar(charset_info, pos, end_of_line)))
"end_of_line" is calculated by "char *end_of_line=line+(uint) strlen(line);" and not used elsewhere

6. mysql-5.0.91/libmysqld/libmysql.c:1648:    if (use_mb_flag && (l = my_ismbchar( mysql->charset, name , end ) ) )
"end" is calculated by "for (end=name; *end ; end++) ;" and not used elsewhere

All these calculations can be eliminated and replaced by charset->mbmaxlen

How to repeat:
By code reviewing
[24 Feb 2011 2:28] Guoliang Jin
I noticed support for 5.0 is stopped, so I update corresponding code in 5.1.55:

1. mysql-5.1.55/sql/item_func.cc:2690:
    register uint32 n=0, l=my_ismbchar(res->charset(),str,str+res->length());
calling length()

2. mysql-5.1.55/sql/item_strfunc.cc:824:
      if ((l= my_ismbchar(res->charset(),ptr,end)))
end calculated by calling length()
other uses of "end" can also be eliminated

3. mysql-5.1.55/sql/item_strfunc.cc:946:
        if ((l=my_ismbchar(res->charset(), ptr,strend))) ptr+=l;
end calculated by calling length()
the other use of "strend" can also be eliminated since the use of "end" can also be eliminated

4. mysql-5.1.55/sql/table.cc:2741:
      int len=my_ismbchar(system_charset_info, name, end);
"strend" is calculated by "char *strend=name+(uint) strlen(name);" and not used
elsewhere

5. mysql-5.1.55/client/mysql.cc:2096:
        (length= my_ismbchar(charset_info, pos, end_of_line)))
"end_of_line" is calculated by "char *end_of_line=line+(uint) strlen(line);" and not used elsewhere

6. mysql-5.1.55/libmysql/libmysql.c:1649:
    if (use_mb_flag && (l = my_ismbchar( mysql->charset, name , end ) ) )
"end" is calculated by "for (end=name; *end ; end++) ;" and not used elsewhere
[14 Mar 2011 4:37] Guoliang Jin
The problem here is that my_ismbchar() does not require the actual length, so calling length() will waste time and it should use mbmaxlen instead.
[25 Mar 2012 12:03] Valeriy Kravchuk
Thank you for the problem report. Verified by code review. Same code is still used in 5.1.62.
[18 Jan 2018 13:17] Erlend Dahl
[11 Jan 2018 18:37] Xing Z Zhang

Bytes passed in might be truncated. It is not safe to use just cs->mbmaxlen
instead of actual string lenth.