github.com/matrixorigin/matrixone@v1.2.0/pkg/sql/plan/function/func_bench_test.go (about)

     1  // Copyright 2024 Matrix Origin
     2  //
     3  // Licensed under the Apache License, Version 2.0 (the "License");
     4  // you may not use this file except in compliance with the License.
     5  // You may obtain a copy of the License at
     6  //
     7  //      http://www.apache.org/licenses/LICENSE-2.0
     8  //
     9  // Unless required by applicable law or agreed to in writing, software
    10  // distributed under the License is distributed on an "AS IS" BASIS,
    11  // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
    12  // See the License for the specific language governing permissions and
    13  // limitations under the License.
    14  
    15  package function
    16  
    17  import (
    18  	"fmt"
    19  	"github.com/matrixorigin/matrixone/pkg/container/types"
    20  	"github.com/matrixorigin/matrixone/pkg/testutil"
    21  	"github.com/stretchr/testify/require"
    22  	"testing"
    23  )
    24  
    25  func initFormatTestCase1() []tcTemp {
    26  	format := `%b %M %m %c %D %d %e %j %k %h %i %p %r %T %s %f %U %u %V %v %a %W %w %X %x %Y %y %%`
    27  
    28  	d1, _ := types.ParseDatetime("2010-01-07 23:12:34.12345", 6)
    29  	r1 := `Jan January 01 1 7th 07 7 007 23 11 12 PM 11:12:34 PM 23:12:34 34 123450 01 01 01 01 Thu Thursday 4 2010 2010 2010 10 %`
    30  
    31  	d2, _ := types.ParseDatetime("2012-12-21 23:12:34.123456", 6)
    32  	r2 := "Dec December 12 12 21st 21 21 356 23 11 12 PM 11:12:34 PM 23:12:34 34 123456 51 51 51 51 Fri Friday 5 2012 2012 2012 12 %"
    33  
    34  	d3, _ := types.ParseDatetime("0001-01-01 00:00:00.123456", 6)
    35  	r3 := `Jan January 01 1 1st 01 1 001 0 12 00 AM 12:00:00 AM 00:00:00 00 123456 00 01 53 01 Mon Monday 1 0000 0001 0001 01 %`
    36  
    37  	d4, _ := types.ParseDatetime("2016-09-3 00:59:59.123456", 6)
    38  	r4 := `Sep September 09 9 3rd 03 3 247 0 12 59 AM 12:59:59 AM 00:59:59 59 123456 35 35 35 35 Sat Saturday 6 2016 2016 2016 16 %`
    39  
    40  	cases := make([]tcTemp, 100)
    41  	for i := range cases {
    42  		values := make([]types.Datetime, 8192)
    43  		nullList := make([]bool, 8192)
    44  		for j := range values {
    45  			mod := j % 4
    46  			if mod == 0 {
    47  				values[j] = d1
    48  				nullList[j] = false
    49  			} else if mod == 1 {
    50  				values[j] = d2
    51  				nullList[j] = false
    52  			} else if mod == 2 {
    53  				values[j] = d3
    54  				nullList[j] = false
    55  			} else {
    56  				values[j] = d4
    57  				nullList[j] = false
    58  			}
    59  		}
    60  		inputs := make([]testutil.FunctionTestInput, 2)
    61  		inputs[0] = testutil.NewFunctionTestInput(types.T_datetime.ToType(), values, nullList)
    62  		inputs[1] = testutil.NewFunctionTestConstInput(types.T_varchar.ToType(), []string{format}, []bool{false})
    63  
    64  		results := make([]string, 8192)
    65  		rnullList := make([]bool, 8192)
    66  		for j := range values {
    67  			mod := j % 4
    68  			if mod == 0 {
    69  				results[j] = r1
    70  				nullList[j] = false
    71  			} else if mod == 1 {
    72  				results[j] = r2
    73  				nullList[j] = false
    74  			} else if mod == 2 {
    75  				results[j] = r3
    76  				nullList[j] = false
    77  			} else {
    78  				results[j] = r4
    79  				nullList[j] = false
    80  			}
    81  		}
    82  
    83  		expect := testutil.NewFunctionTestResult(types.T_varchar.ToType(), false, results, rnullList)
    84  
    85  		cases[i] = tcTemp{
    86  			info:   "test format",
    87  			typ:    types.T_datetime,
    88  			inputs: inputs,
    89  			expect: expect,
    90  		}
    91  	}
    92  	return cases
    93  }
    94  
    95  // BenchmarkDateFormat1-4   	1000000000	         2.462 ns/op
    96  func BenchmarkDateFormat1(b *testing.B) {
    97  	//b.N = 1000000000
    98  	testCases := initFormatTestCase1()
    99  	// do the test work.
   100  	proc := testutil.NewProcess()
   101  	for _, tc := range testCases {
   102  		fcTC := testutil.NewFunctionTestCase(proc, tc.inputs, tc.expect, DateFormat)
   103  		fcTC.BenchMarkRun()
   104  		_, _ = fcTC.Run()
   105  	}
   106  }
   107  
   108  func initFormatTestCase2() []tcTemp {
   109  	format := `%Y,%m,%d %H:%i:%s`
   110  
   111  	d1, _ := types.ParseDatetime("2010-01-07 23:12:34.12345", 6)
   112  	r1 := `2010,01,07 23:12:34`
   113  
   114  	d2, _ := types.ParseDatetime("2012-12-21 23:12:34.123456", 6)
   115  	r2 := "2012,12,21 23:12:34"
   116  
   117  	d3, _ := types.ParseDatetime("2021-01-01 00:00:00.123456", 6)
   118  	r3 := `2021,01,01 00:00:00`
   119  
   120  	d4, _ := types.ParseDatetime("2016-09-3 00:59:59.123456", 6)
   121  	r4 := `2016,09,03 00:59:59`
   122  
   123  	cases := make([]tcTemp, 100)
   124  	for i := range cases {
   125  		values := make([]types.Datetime, 8192)
   126  		nullList := make([]bool, 8192)
   127  		for j := range values {
   128  			mod := j % 4
   129  			if mod == 0 {
   130  				values[j] = d1
   131  				nullList[j] = false
   132  			} else if mod == 1 {
   133  				values[j] = d2
   134  				nullList[j] = false
   135  			} else if mod == 2 {
   136  				values[j] = d3
   137  				nullList[j] = false
   138  			} else {
   139  				values[j] = d4
   140  				nullList[j] = false
   141  			}
   142  		}
   143  		inputs := make([]testutil.FunctionTestInput, 2)
   144  		inputs[0] = testutil.NewFunctionTestInput(types.T_datetime.ToType(), values, nullList)
   145  		inputs[1] = testutil.NewFunctionTestConstInput(types.T_varchar.ToType(), []string{format}, []bool{false})
   146  
   147  		results := make([]string, 8192)
   148  		rnullList := make([]bool, 8192)
   149  		for j := range values {
   150  			mod := j % 4
   151  			if mod == 0 {
   152  				results[j] = r1
   153  				nullList[j] = false
   154  			} else if mod == 1 {
   155  				results[j] = r2
   156  				nullList[j] = false
   157  			} else if mod == 2 {
   158  				results[j] = r3
   159  				nullList[j] = false
   160  			} else {
   161  				results[j] = r4
   162  				nullList[j] = false
   163  			}
   164  		}
   165  
   166  		expect := testutil.NewFunctionTestResult(types.T_varchar.ToType(), false, results, rnullList)
   167  
   168  		cases[i] = tcTemp{
   169  			info:   "test format",
   170  			typ:    types.T_datetime,
   171  			inputs: inputs,
   172  			expect: expect,
   173  		}
   174  	}
   175  	return cases
   176  }
   177  
   178  // BenchmarkDateFormat2-4   	1000000000	         0.3115 ns/op
   179  func BenchmarkDateFormat2(b *testing.B) {
   180  	//b.N = 1000000000
   181  	testCases := initFormatTestCase2()
   182  	// do the test work.
   183  	proc := testutil.NewProcess()
   184  	for _, tc := range testCases {
   185  		fcTC := testutil.NewFunctionTestCase(proc, tc.inputs, tc.expect, DateFormat)
   186  		fcTC.BenchMarkRun()
   187  		_, _ = fcTC.Run()
   188  	}
   189  }
   190  
   191  func initFormatTestCase3() []tcTemp {
   192  	format := `%Y-%m-%d`
   193  
   194  	d1, _ := types.ParseDatetime("2010-01-07 23:12:34.12345", 6)
   195  	r1 := `2010-01-07`
   196  
   197  	d2, _ := types.ParseDatetime("2012-12-21 23:12:34.123456", 6)
   198  	r2 := "2012-12-21"
   199  
   200  	d3, _ := types.ParseDatetime("2021-01-01 00:00:00.123456", 6)
   201  	r3 := `2021-01-01`
   202  
   203  	d4, _ := types.ParseDatetime("2016-09-3 00:59:59.123456", 6)
   204  	r4 := `2016-09-03`
   205  
   206  	cases := make([]tcTemp, 100)
   207  	for i := range cases {
   208  		values := make([]types.Datetime, 8192)
   209  		nullList := make([]bool, 8192)
   210  		for j := range values {
   211  			mod := j % 4
   212  			if mod == 0 {
   213  				values[j] = d1
   214  				nullList[j] = false
   215  			} else if mod == 1 {
   216  				values[j] = d2
   217  				nullList[j] = false
   218  			} else if mod == 2 {
   219  				values[j] = d3
   220  				nullList[j] = false
   221  			} else {
   222  				values[j] = d4
   223  				nullList[j] = false
   224  			}
   225  		}
   226  		inputs := make([]testutil.FunctionTestInput, 2)
   227  		inputs[0] = testutil.NewFunctionTestInput(types.T_datetime.ToType(), values, nullList)
   228  		inputs[1] = testutil.NewFunctionTestConstInput(types.T_varchar.ToType(), []string{format}, []bool{false})
   229  
   230  		results := make([]string, 8192)
   231  		rnullList := make([]bool, 8192)
   232  		for j := range values {
   233  			mod := j % 4
   234  			if mod == 0 {
   235  				results[j] = r1
   236  				nullList[j] = false
   237  			} else if mod == 1 {
   238  				results[j] = r2
   239  				nullList[j] = false
   240  			} else if mod == 2 {
   241  				results[j] = r3
   242  				nullList[j] = false
   243  			} else {
   244  				results[j] = r4
   245  				nullList[j] = false
   246  			}
   247  		}
   248  
   249  		expect := testutil.NewFunctionTestResult(types.T_varchar.ToType(), false, results, rnullList)
   250  
   251  		cases[i] = tcTemp{
   252  			info:   "test format",
   253  			typ:    types.T_datetime,
   254  			inputs: inputs,
   255  			expect: expect,
   256  		}
   257  	}
   258  	return cases
   259  }
   260  
   261  // BenchmarkDateFormat3-4   	1000000000	         0.1523 ns/op
   262  func BenchmarkDateFormat3(b *testing.B) {
   263  	//b.N = 1000000000
   264  	testCases := initFormatTestCase3()
   265  	// do the test work.
   266  	proc := testutil.NewProcess()
   267  	for _, tc := range testCases {
   268  		fcTC := testutil.NewFunctionTestCase(proc, tc.inputs, tc.expect, DateFormat)
   269  		fcTC.BenchMarkRun()
   270  		_, _ = fcTC.Run()
   271  	}
   272  }
   273  
   274  func initFormatTestCase4() []tcTemp {
   275  	format := `%Y/%m/%d`
   276  
   277  	d1, _ := types.ParseDatetime("2010-01-07 23:12:34.12345", 6)
   278  	r1 := `2010/01/07`
   279  
   280  	d2, _ := types.ParseDatetime("2012-12-21 23:12:34.123456", 6)
   281  	r2 := "2012/12/21"
   282  
   283  	d3, _ := types.ParseDatetime("2021-01-01 00:00:00.123456", 6)
   284  	r3 := `2021/01/01`
   285  
   286  	d4, _ := types.ParseDatetime("2016-09-3 00:59:59.123456", 6)
   287  	r4 := `2016/09/03`
   288  
   289  	cases := make([]tcTemp, 100)
   290  	for i := range cases {
   291  		values := make([]types.Datetime, 8192)
   292  		nullList := make([]bool, 8192)
   293  		for j := range values {
   294  			mod := j % 4
   295  			if mod == 0 {
   296  				values[j] = d1
   297  				nullList[j] = false
   298  			} else if mod == 1 {
   299  				values[j] = d2
   300  				nullList[j] = false
   301  			} else if mod == 2 {
   302  				values[j] = d3
   303  				nullList[j] = false
   304  			} else {
   305  				values[j] = d4
   306  				nullList[j] = false
   307  			}
   308  		}
   309  		inputs := make([]testutil.FunctionTestInput, 2)
   310  		inputs[0] = testutil.NewFunctionTestInput(types.T_datetime.ToType(), values, nullList)
   311  		inputs[1] = testutil.NewFunctionTestConstInput(types.T_varchar.ToType(), []string{format}, []bool{false})
   312  
   313  		results := make([]string, 8192)
   314  		rnullList := make([]bool, 8192)
   315  		for j := range values {
   316  			mod := j % 4
   317  			if mod == 0 {
   318  				results[j] = r1
   319  				nullList[j] = false
   320  			} else if mod == 1 {
   321  				results[j] = r2
   322  				nullList[j] = false
   323  			} else if mod == 2 {
   324  				results[j] = r3
   325  				nullList[j] = false
   326  			} else {
   327  				results[j] = r4
   328  				nullList[j] = false
   329  			}
   330  		}
   331  
   332  		expect := testutil.NewFunctionTestResult(types.T_varchar.ToType(), false, results, rnullList)
   333  
   334  		cases[i] = tcTemp{
   335  			info:   "test format",
   336  			typ:    types.T_datetime,
   337  			inputs: inputs,
   338  			expect: expect,
   339  		}
   340  	}
   341  	return cases
   342  }
   343  
   344  // BenchmarkDateFormat4-4   	1000000000	         0.1541 ns/op
   345  func BenchmarkDateFormat4(b *testing.B) {
   346  	//b.N = 1000000000
   347  	testCases := initFormatTestCase4()
   348  	// do the test work.
   349  	proc := testutil.NewProcess()
   350  	for _, tc := range testCases {
   351  		fcTC := testutil.NewFunctionTestCase(proc, tc.inputs, tc.expect, DateFormat)
   352  		fcTC.BenchMarkRun()
   353  		_, _ = fcTC.Run()
   354  	}
   355  }
   356  
   357  func initFormatTestCase5() []tcTemp {
   358  	format := `%Y-%m-%d %H:%i:%s`
   359  
   360  	d1, _ := types.ParseDatetime("2010-01-07 23:12:34.12345", 6)
   361  	r1 := `2010-01-07 23:12:34`
   362  
   363  	d2, _ := types.ParseDatetime("2012-12-21 23:12:34.123456", 6)
   364  	r2 := "2012-12-21 23:12:34"
   365  
   366  	d3, _ := types.ParseDatetime("2021-01-01 00:00:00.123456", 6)
   367  	r3 := `2021-01-01 00:00:00`
   368  
   369  	d4, _ := types.ParseDatetime("2016-09-3 00:59:59.123456", 6)
   370  	r4 := `2016-09-03 00:59:59`
   371  
   372  	cases := make([]tcTemp, 100)
   373  	for i := range cases {
   374  		values := make([]types.Datetime, 8192)
   375  		nullList := make([]bool, 8192)
   376  		for j := range values {
   377  			mod := j % 4
   378  			if mod == 0 {
   379  				values[j] = d1
   380  				nullList[j] = false
   381  			} else if mod == 1 {
   382  				values[j] = d2
   383  				nullList[j] = false
   384  			} else if mod == 2 {
   385  				values[j] = d3
   386  				nullList[j] = false
   387  			} else {
   388  				values[j] = d4
   389  				nullList[j] = false
   390  			}
   391  		}
   392  		inputs := make([]testutil.FunctionTestInput, 2)
   393  		inputs[0] = testutil.NewFunctionTestInput(types.T_datetime.ToType(), values, nullList)
   394  		inputs[1] = testutil.NewFunctionTestConstInput(types.T_varchar.ToType(), []string{format}, []bool{false})
   395  
   396  		results := make([]string, 8192)
   397  		rnullList := make([]bool, 8192)
   398  		for j := range values {
   399  			mod := j % 4
   400  			if mod == 0 {
   401  				results[j] = r1
   402  				nullList[j] = false
   403  			} else if mod == 1 {
   404  				results[j] = r2
   405  				nullList[j] = false
   406  			} else if mod == 2 {
   407  				results[j] = r3
   408  				nullList[j] = false
   409  			} else {
   410  				results[j] = r4
   411  				nullList[j] = false
   412  			}
   413  		}
   414  
   415  		expect := testutil.NewFunctionTestResult(types.T_varchar.ToType(), false, results, rnullList)
   416  
   417  		cases[i] = tcTemp{
   418  			info:   "test format",
   419  			typ:    types.T_datetime,
   420  			inputs: inputs,
   421  			expect: expect,
   422  		}
   423  	}
   424  	return cases
   425  }
   426  
   427  // BenchmarkDateFormat5-4   	1000000000	         0.2022 ns/op
   428  func BenchmarkDateFormat5(b *testing.B) {
   429  	//b.N = 1000000000
   430  	testCases := initFormatTestCase5()
   431  	// do the test work.
   432  	proc := testutil.NewProcess()
   433  	for _, tc := range testCases {
   434  		fcTC := testutil.NewFunctionTestCase(proc, tc.inputs, tc.expect, DateFormat)
   435  		fcTC.BenchMarkRun()
   436  		_, _ = fcTC.Run()
   437  	}
   438  }
   439  
   440  func initFormatTestCase6() []tcTemp {
   441  	format := `%Y/%m/%d %H:%i:%s`
   442  
   443  	d1, _ := types.ParseDatetime("2010-01-07 23:12:34.12345", 6)
   444  	r1 := `2010/01/07 23:12:34`
   445  
   446  	d2, _ := types.ParseDatetime("2012-12-21 23:12:34.123456", 6)
   447  	r2 := "2012/12/21 23:12:34"
   448  
   449  	d3, _ := types.ParseDatetime("2021-01-01 00:00:00.123456", 6)
   450  	r3 := `2021/01/01 00:00:00`
   451  
   452  	d4, _ := types.ParseDatetime("2016-09-3 00:59:59.123456", 6)
   453  	r4 := `2016/09/03 00:59:59`
   454  
   455  	cases := make([]tcTemp, 100)
   456  	for i := range cases {
   457  		values := make([]types.Datetime, 8192)
   458  		nullList := make([]bool, 8192)
   459  		for j := range values {
   460  			mod := j % 4
   461  			if mod == 0 {
   462  				values[j] = d1
   463  				nullList[j] = false
   464  			} else if mod == 1 {
   465  				values[j] = d2
   466  				nullList[j] = false
   467  			} else if mod == 2 {
   468  				values[j] = d3
   469  				nullList[j] = false
   470  			} else {
   471  				values[j] = d4
   472  				nullList[j] = false
   473  			}
   474  		}
   475  		inputs := make([]testutil.FunctionTestInput, 2)
   476  		inputs[0] = testutil.NewFunctionTestInput(types.T_datetime.ToType(), values, nullList)
   477  		inputs[1] = testutil.NewFunctionTestConstInput(types.T_varchar.ToType(), []string{format}, []bool{false})
   478  
   479  		results := make([]string, 8192)
   480  		rnullList := make([]bool, 8192)
   481  		for j := range values {
   482  			mod := j % 4
   483  			if mod == 0 {
   484  				results[j] = r1
   485  				nullList[j] = false
   486  			} else if mod == 1 {
   487  				results[j] = r2
   488  				nullList[j] = false
   489  			} else if mod == 2 {
   490  				results[j] = r3
   491  				nullList[j] = false
   492  			} else {
   493  				results[j] = r4
   494  				nullList[j] = false
   495  			}
   496  		}
   497  
   498  		expect := testutil.NewFunctionTestResult(types.T_varchar.ToType(), false, results, rnullList)
   499  
   500  		cases[i] = tcTemp{
   501  			info:   "test format",
   502  			typ:    types.T_datetime,
   503  			inputs: inputs,
   504  			expect: expect,
   505  		}
   506  	}
   507  	return cases
   508  }
   509  
   510  // BenchmarkDateFormat6-4   	1000000000	         0.1927 ns/op
   511  func BenchmarkDateFormat6(b *testing.B) {
   512  	//b.N = 1000000000
   513  	testCases := initFormatTestCase6()
   514  	// do the test work.
   515  	proc := testutil.NewProcess()
   516  	for _, tc := range testCases {
   517  		fcTC := testutil.NewFunctionTestCase(proc, tc.inputs, tc.expect, DateFormat)
   518  		fcTC.BenchMarkRun()
   519  		_, _ = fcTC.Run()
   520  	}
   521  }
   522  
   523  //DATE_FORMAT string      Formatted date
   524  // %d/%m/%Y	               22/04/2021
   525  // %Y%m%d	               20210422
   526  // %Y                      2021
   527  // %Y-%m-%d	               2021-04-22
   528  // %Y-%m-%d %H:%i:%s       2004-04-03 13:11:10
   529  // %Y/%m/%d                2010/01/07
   530  // %Y/%m/%d %H:%i:%s       2010/01/07 23:12:34
   531  
   532  func TestDateFormat(t *testing.T) {
   533  	testCases1 := initFormatTestCase1()
   534  
   535  	// do the test work.
   536  	proc := testutil.NewProcess()
   537  	for _, tc := range testCases1 {
   538  		fcTC := testutil.NewFunctionTestCase(proc,
   539  			tc.inputs, tc.expect, DateFormat)
   540  		s, info := fcTC.Run()
   541  		require.True(t, s, fmt.Sprintf("case is '%s', err info is '%s'", tc.info, info))
   542  	}
   543  
   544  	testCases2 := initFormatTestCase2()
   545  	// do the test work.
   546  	for _, tc := range testCases2 {
   547  		fcTC := testutil.NewFunctionTestCase(proc,
   548  			tc.inputs, tc.expect, DateFormat)
   549  		s, info := fcTC.Run()
   550  		require.True(t, s, fmt.Sprintf("case is '%s', err info is '%s'", tc.info, info))
   551  	}
   552  
   553  	testCases3 := initFormatTestCase3()
   554  	// do the test work.
   555  	for _, tc := range testCases3 {
   556  		fcTC := testutil.NewFunctionTestCase(proc,
   557  			tc.inputs, tc.expect, DateFormat)
   558  		s, info := fcTC.Run()
   559  		require.True(t, s, fmt.Sprintf("case is '%s', err info is '%s'", tc.info, info))
   560  	}
   561  
   562  	testCases4 := initFormatTestCase4()
   563  	// do the test work.
   564  	for _, tc := range testCases4 {
   565  		fcTC := testutil.NewFunctionTestCase(proc,
   566  			tc.inputs, tc.expect, DateFormat)
   567  		s, info := fcTC.Run()
   568  		require.True(t, s, fmt.Sprintf("case is '%s', err info is '%s'", tc.info, info))
   569  	}
   570  
   571  	testCases5 := initFormatTestCase5()
   572  	// do the test work.
   573  	for _, tc := range testCases5 {
   574  		fcTC := testutil.NewFunctionTestCase(proc,
   575  			tc.inputs, tc.expect, DateFormat)
   576  		s, info := fcTC.Run()
   577  		require.True(t, s, fmt.Sprintf("case is '%s', err info is '%s'", tc.info, info))
   578  	}
   579  
   580  	testCases6 := initFormatTestCase6()
   581  	// do the test work.
   582  	for _, tc := range testCases6 {
   583  		fcTC := testutil.NewFunctionTestCase(proc,
   584  			tc.inputs, tc.expect, DateFormat)
   585  		s, info := fcTC.Run()
   586  		require.True(t, s, fmt.Sprintf("case is '%s', err info is '%s'", tc.info, info))
   587  	}
   588  }