[MDEV-23568] Improve performance of my_{time|date|datetime}_to_str() Created: 2020-08-25  Updated: 2020-10-06  Resolved: 2020-08-28

Status: Closed
Project: MariaDB Server
Component/s: Data types
Fix Version/s: 10.5.7

Type: Task Priority: Major
Reporter: Alexander Barkov Assignee: Alexander Barkov
Resolution: Fixed Votes: 0
Labels: None

Attachments: File fmt.diff    

 Description   

The MySQL-8.0 code base has an interesting change improving number-to-string conversion:

commit 8d10f2fff6bbdea7f436b868ebb5fd811defc68a
Author: Knut Anders Hatlen <knut.hatlen@oracle.com>
Date:   Thu Oct 10 13:55:07 2019 +0200
 
    Bug#30472888: IMPROVE THE PERFORMANCE OF INTEGER HANDLING IN THE TEXT PROTOCOL

The idea is that the division and the remainder operations used to print zerofill numbers appeared to be slow.
It's cheaper to have a 200-byte long string consisting of precomposed 2-digit substrings strings, e.g. "00", "01", ... "99", and copy a proper 2-digit substring from this string, by index:

static const char two_digit_numbers[]=
{
  "00010203040506070809"
  "10111213141516171819"
  "20212223242526272829"
  "30313233343536373839"
  "40414243444546474849"
  "50515253545556575859"
  "60616263646566676869"
  "70717273747576777879"
  "80818283848586878889"
  "90919293949596979899"
};

This function prints a 2-digit number:

static inline char* fmt_number2(uint8 val, char *out)
{
  const char *src= two_digit_numbers + val * 2;
  DBUG_ASSERT(val < 100);
  *out++= *src++;
  *out++= *src++;
  return out;
}

The performance is achieved by the fact that it prints two digits at a time.

Let's reuse this optimization in the following functions:

  • my_date_to_str()
  • my_time_to_str()
  • my_datetime_to_str()
  • my_interval_DDhhmmssff_to_str()
  • my_timeval_to_str
  • my_mmssff_to_str() - an internal function used in the above public functions

Benchmarks

A preliminary patch to MariaDB (that uses this idea) indeed demonstrates a very impressing query time reduce - 10% to 38%, depending on the exact data type and the number of fractional digits.

SELECT BENCHMARK(10*1000*1000,CONCAT(TIME'10:20:30'));

10.5: 0.176 65ee216c35d843da7883d255219ab011e20340c2
10.5: 0.167 (my_xxx_to_str() improvements)

SELECT BENCHMARK(10*1000*1000,CONCAT(TIME'10:20:30.123456'));

10.5: 0.288 65ee216c35d843da7883d255219ab011e20340c2
10.5: 0.261 (my_xxx_to_str() improvements)

SELECT BENCHMARK(10*1000*1000,CONCAT(DATE'2001-01-01'));

10.5: 0.258 65ee216c35d843da7883d255219ab011e20340c2
10.5: 0.225 (my_xxx_to_str() improvements)

SELECT BENCHMARK(10*1000*1000,CONCAT(TIMESTAMP'2001-01-01 10:20:30'));

10.5: 0.319 65ee216c35d843da7883d255219ab011e20340c2
10.5: 0.268 (my_xxx_to_str() improvements)

SELECT BENCHMARK(10*1000*1000,CONCAT(TIMESTAMP'2001-01-01 10:20:30.123456'));

10.5: 0.438 65ee216c35d843da7883d255219ab011e20340c2
10.5: 0.275 (my_xxx_to_str() improvements)


Generated at Thu Feb 08 09:23:23 UTC 2024 using Jira 8.20.16#820016-sha1:9d11dbea5f4be3d4cc21f03a88dd11d8c8687422.