github.com/matrixorigin/matrixone@v0.7.0/pkg/sql/colexec/group/group_bench_test.go (about)

     1  // Copyright 2021 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 group
    16  
    17  import (
    18  	"encoding/json"
    19  	"testing"
    20  	"time"
    21  
    22  	"github.com/matrixorigin/matrixone/pkg/common/mpool"
    23  	"github.com/matrixorigin/matrixone/pkg/container/index"
    24  	"github.com/matrixorigin/matrixone/pkg/container/types"
    25  	"github.com/matrixorigin/matrixone/pkg/container/vector"
    26  	"github.com/matrixorigin/matrixone/pkg/pb/plan"
    27  	"github.com/matrixorigin/matrixone/pkg/sql/colexec/agg"
    28  	"github.com/matrixorigin/matrixone/pkg/testutil"
    29  	"github.com/stretchr/testify/require"
    30  )
    31  
    32  const (
    33  	benchFlag        = false
    34  	benchCardinality = 1024
    35  
    36  	benchTargetRows = 5_000
    37  )
    38  
    39  var (
    40  	benchGroupData  []string
    41  	benchGroupIndex *index.LowCardinalityIndex
    42  )
    43  
    44  func init() {
    45  	if !benchFlag {
    46  		return
    47  	}
    48  
    49  	benchGroupData = testutil.MakeRandomStrings(benchCardinality, benchTargetRows)
    50  
    51  	var err error
    52  	if benchGroupIndex, err = initBenchIndex(benchGroupData); err != nil {
    53  		panic(err)
    54  	}
    55  }
    56  
    57  func initBenchIndex(values []string) (*index.LowCardinalityIndex, error) {
    58  	var err error
    59  	m := mpool.MustNewZero()
    60  	v := testutil.NewVector(len(values), types.T_varchar.ToType(), m, false, values)
    61  	idx, err := index.New(v.Typ, m)
    62  	if err != nil {
    63  		return nil, err
    64  	}
    65  	if err = idx.InsertBatch(v); err != nil {
    66  		return nil, err
    67  	}
    68  	return idx, nil
    69  }
    70  
    71  func TestGroupPerf(t *testing.T) {
    72  	if !benchFlag {
    73  		t.Log("benchmark flag is turned off...")
    74  		return
    75  	}
    76  
    77  	const testCnt = 10
    78  
    79  	metricMp := map[string][]int64{
    80  		"totalCost":              make([]int64, testCnt),
    81  		"constructGroupDataCost": make([]int64, testCnt),
    82  		"groupbyCost":            make([]int64, testCnt),
    83  	}
    84  	avgMp := map[string]int64{
    85  		"totalCost":              0,
    86  		"constructGroupDataCost": 0,
    87  		"groupbyCost":            0,
    88  	}
    89  
    90  	//----------------
    91  	// common group by
    92  	//----------------
    93  	{
    94  		t.Log("---------- test common group by performance ----------")
    95  		for i := 0; i < testCnt; i++ {
    96  			mockTimingCase(t, metricMp, i, nil)
    97  		}
    98  
    99  		metric, err := json.Marshal(metricMp)
   100  		require.NoError(t, err)
   101  		t.Logf("common group by performance metric: \n%s\n", string(metric))
   102  
   103  		avg := calcAvg(t, testCnt, metricMp, avgMp)
   104  		t.Logf("common group by performance average: \n%s\n", avg)
   105  	}
   106  
   107  	t.Logf("\n")
   108  
   109  	//-------------------------
   110  	// low cardinality group by
   111  	//-------------------------
   112  	{
   113  		t.Log("---------- test low cardinality group by performance ----------")
   114  		for i := 0; i < testCnt; i++ {
   115  			mockTimingCase(t, metricMp, i, benchGroupIndex.Dup())
   116  		}
   117  
   118  		metric, err := json.Marshal(metricMp)
   119  		require.NoError(t, err)
   120  		t.Logf("low cardinality group by performance metric: \n%s\n", string(metric))
   121  
   122  		avg := calcAvg(t, testCnt, metricMp, avgMp)
   123  		t.Logf("low cardinality group by performance average: \n%s\n", avg)
   124  	}
   125  }
   126  
   127  func mockTimingCase(t *testing.T, metricMp map[string][]int64, pos int, idx *index.LowCardinalityIndex) {
   128  	totalStart := time.Now().UnixNano()
   129  	// SELECT COUNT(*) FROM t GROUP BY t.col
   130  	tc := newTestCase([]bool{false}, []types.Type{{Oid: types.T_varchar}},
   131  		[]*plan.Expr{newExpression(0)}, []agg.Aggregate{{Op: 5, E: newExpression(0)}})
   132  
   133  	// construct group data part
   134  	constructGroupDataStart := time.Now().UnixNano()
   135  	v := testutil.NewVector(len(benchGroupData), types.T_varchar.ToType(), tc.proc.Mp(), false, benchGroupData)
   136  	if idx != nil {
   137  		v.SetIndex(idx)
   138  	}
   139  	constructGroupDataEnd := time.Now().UnixNano()
   140  	metricMp["constructGroupDataCost"][pos] = constructGroupDataEnd - constructGroupDataStart
   141  
   142  	// group by part
   143  	groupbyStart := time.Now().UnixNano()
   144  	err := Prepare(tc.proc, tc.arg)
   145  	require.NoError(t, err)
   146  	tc.proc.Reg.InputBatch = testutil.NewBatchWithVectors([]*vector.Vector{v}, nil)
   147  	_, err = Call(0, tc.proc, tc.arg, false, false)
   148  	require.NoError(t, err)
   149  	groupbyEnd := time.Now().UnixNano()
   150  	metricMp["groupbyCost"][pos] = groupbyEnd - groupbyStart
   151  
   152  	if tc.proc.Reg.InputBatch != nil {
   153  		tc.proc.Reg.InputBatch.Clean(tc.proc.Mp())
   154  	}
   155  
   156  	totalEnd := time.Now().UnixNano()
   157  	metricMp["totalCost"][pos] = totalEnd - totalStart
   158  }
   159  
   160  func calcAvg(t *testing.T, cnt int64, perf map[string][]int64, avg map[string]int64) string {
   161  	for k, data := range perf {
   162  		sum := int64(0)
   163  		for _, v := range data {
   164  			sum += v
   165  		}
   166  		avg[k] = sum / cnt
   167  	}
   168  
   169  	res, err := json.Marshal(avg)
   170  	require.NoError(t, err)
   171  	return string(res)
   172  }