summaryrefslogtreecommitdiff
path: root/sql-common
diff options
context:
space:
mode:
authorAlexander Barkov <bar@mariadb.com>2020-08-29 11:24:13 +0400
committerAlexander Barkov <bar@mariadb.com>2020-09-03 06:03:54 +0400
commit48ab5a4997b073f98d8d521045f14a4ec211ed1b (patch)
tree6ce9b434e4d52bf2c40d8bfeb0e17bb1e71e395d /sql-common
parent0af6e525212f81c2da8185817c6ca2e7c3ac036a (diff)
downloadmariadb-git-48ab5a4997b073f98d8d521045f14a4ec211ed1b.tar.gz
Part2: MDEV-23568 Improve performance of my_{time|date|datetime}_to_str()
As an additional improvement, let's store string representations of the numbers using an array uint16[256] instead of char[512]. This allows to use int2store(), which copies two bytes at a time on x86, instead of copying the two bytes with digits one-by-one. This change gives an additional 7% to 26% query time reduce for: SELECT BENCHMARK(10*1000*1000,CONCAT(TIME'10:20:30')); SELECT BENCHMARK(10*1000*1000,CONCAT(TIME'10:20:30.123456')); SELECT BENCHMARK(10*1000*1000,CONCAT(DATE'2001-01-01')); SELECT BENCHMARK(10*1000*1000,CONCAT(TIMESTAMP'2001-01-01 10:20:30')); SELECT BENCHMARK(10*1000*1000,CONCAT(TIMESTAMP'2001-01-01 10:20:30.123456')); The total time reduce (part1 + part2) is now between 15% to 38% for these queries.
Diffstat (limited to 'sql-common')
-rw-r--r--sql-common/my_time.c85
1 files changed, 49 insertions, 36 deletions
diff --git a/sql-common/my_time.c b/sql-common/my_time.c
index 563ca00d59f..96674723b34 100644
--- a/sql-common/my_time.c
+++ b/sql-common/my_time.c
@@ -1471,55 +1471,68 @@ void set_zero_time(MYSQL_TIME *tm, enum enum_mysql_timestamp_type time_type)
SELECT BENCHMARK(10*1000*1000,CONCAT(TIMESTAMP'2001-01-01 10:20:30.123456'));
(depending on the exact data type and fractional precision).
- The array has extra elements for uint8 values 100..255.
+ The array has extra elements for values 100..255.
This is done for safety. If the caller passes a value
- outside of the expected range 0..99, it will be printed as "XX".
-*/
+ outside of the expected range 0..99, the value will be printed as "XX".
+
+ Part2:
+
+ As an additional improvement over "class TwoDigitWriter", we store
+ the string representations of the numbers in an array uint16[256]
+ instead of char[512]. This allows to copy data using int2store(),
+ which copies two bytes at a time on x86 and gives an additional
+ 7% to 26% time reduce over copying the two bytes separately.
+
+ The total time reduce is 15% to 38% on the above queries.
-static const char two_digit_numbers[512+1]=
+ The bytes in the following array are swapped:
+ e.g. 0x3130 in two_digit_numbers[1] means the following:
+ - 0x31 is '1' (the left byte, the right digit)
+ - 0x30 is '0' (the right byte, the left digit)
+ int2store() puts the lower byte first, so the output string becomes '01'.
+*/
+static const uint16 two_digit_numbers[256]=
{
/* 0..99 */
- "00010203040506070809"
- "10111213141516171819"
- "20212223242526272829"
- "30313233343536373839"
- "40414243444546474849"
- "50515253545556575859"
- "60616263646566676869"
- "70717273747576777879"
- "80818283848586878889"
- "90919293949596979899"
+ 0x3030,0x3130,0x3230,0x3330,0x3430,0x3530,0x3630,0x3730,0x3830,0x3930,
+ 0x3031,0x3131,0x3231,0x3331,0x3431,0x3531,0x3631,0x3731,0x3831,0x3931,
+ 0x3032,0x3132,0x3232,0x3332,0x3432,0x3532,0x3632,0x3732,0x3832,0x3932,
+ 0x3033,0x3133,0x3233,0x3333,0x3433,0x3533,0x3633,0x3733,0x3833,0x3933,
+ 0x3034,0x3134,0x3234,0x3334,0x3434,0x3534,0x3634,0x3734,0x3834,0x3934,
+ 0x3035,0x3135,0x3235,0x3335,0x3435,0x3535,0x3635,0x3735,0x3835,0x3935,
+ 0x3036,0x3136,0x3236,0x3336,0x3436,0x3536,0x3636,0x3736,0x3836,0x3936,
+ 0x3037,0x3137,0x3237,0x3337,0x3437,0x3537,0x3637,0x3737,0x3837,0x3937,
+ 0x3038,0x3138,0x3238,0x3338,0x3438,0x3538,0x3638,0x3738,0x3838,0x3938,
+ 0x3039,0x3139,0x3239,0x3339,0x3439,0x3539,0x3639,0x3739,0x3839,0x3939,
/* 100..199 - safety */
- "XXXXXXXXXXXXXXXXXXXX"
- "XXXXXXXXXXXXXXXXXXXX"
- "XXXXXXXXXXXXXXXXXXXX"
- "XXXXXXXXXXXXXXXXXXXX"
- "XXXXXXXXXXXXXXXXXXXX"
- "XXXXXXXXXXXXXXXXXXXX"
- "XXXXXXXXXXXXXXXXXXXX"
- "XXXXXXXXXXXXXXXXXXXX"
- "XXXXXXXXXXXXXXXXXXXX"
- "XXXXXXXXXXXXXXXXXXXX"
+ 0x5858,0x5858,0x5858,0x5858,0x5858,0x5858,0x5858,0x5858,0x5858,0x5858,
+ 0x5858,0x5858,0x5858,0x5858,0x5858,0x5858,0x5858,0x5858,0x5858,0x5858,
+ 0x5858,0x5858,0x5858,0x5858,0x5858,0x5858,0x5858,0x5858,0x5858,0x5858,
+ 0x5858,0x5858,0x5858,0x5858,0x5858,0x5858,0x5858,0x5858,0x5858,0x5858,
+ 0x5858,0x5858,0x5858,0x5858,0x5858,0x5858,0x5858,0x5858,0x5858,0x5858,
+ 0x5858,0x5858,0x5858,0x5858,0x5858,0x5858,0x5858,0x5858,0x5858,0x5858,
+ 0x5858,0x5858,0x5858,0x5858,0x5858,0x5858,0x5858,0x5858,0x5858,0x5858,
+ 0x5858,0x5858,0x5858,0x5858,0x5858,0x5858,0x5858,0x5858,0x5858,0x5858,
+ 0x5858,0x5858,0x5858,0x5858,0x5858,0x5858,0x5858,0x5858,0x5858,0x5858,
+ 0x5858,0x5858,0x5858,0x5858,0x5858,0x5858,0x5858,0x5858,0x5858,0x5858,
/* 200..255 - safety */
- "XXXXXXXXXXXXXXXXXXXX"
- "XXXXXXXXXXXXXXXXXXXX"
- "XXXXXXXXXXXXXXXXXXXX"
- "XXXXXXXXXXXXXXXXXXXX"
- "XXXXXXXXXXXXXXXXXXXX"
- "XXXXXXXXXXXX"
+ 0x5858,0x5858,0x5858,0x5858,0x5858,0x5858,0x5858,0x5858,0x5858,0x5858,
+ 0x5858,0x5858,0x5858,0x5858,0x5858,0x5858,0x5858,0x5858,0x5858,0x5858,
+ 0x5858,0x5858,0x5858,0x5858,0x5858,0x5858,0x5858,0x5858,0x5858,0x5858,
+ 0x5858,0x5858,0x5858,0x5858,0x5858,0x5858,0x5858,0x5858,0x5858,0x5858,
+ 0x5858,0x5858,0x5858,0x5858,0x5858,0x5858,0x5858,0x5858,0x5858,0x5858,
+ 0x5858,0x5858,0x5858,0x5858,0x5858,0x5858,
};
-
static inline char* fmt_number2(uint8 val, char *out)
{
- const char *src= two_digit_numbers + val * 2;
- *out++= *src++;
- *out++= *src++;
- return out;
+ int2store(out, two_digit_numbers[val]);
+ return out + 2;
}
+
/*
- We tried the same trick with an array of 16384 zerofill 4-digit numbers,
+ We tried the same trick with a char array of 16384 zerofill 4-digit numbers,
with 10000 elements with numbers 0000..9999, and a tail filled with "XXXX".
Benchmark results for a RelWithDebInfo build: