tidb builtin_vectorized 源码

  • 2022-09-19
  • 浏览 (445)

tidb builtin_vectorized 代码

文件路径:/expression/builtin_vectorized.go

// Copyright 2019 PingCAP, Inc.
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
//     http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.

package expression

import (
	"sync"
	"unsafe"

	"github.com/pingcap/errors"
	"github.com/pingcap/tidb/parser/mysql"
	"github.com/pingcap/tidb/types"
	"github.com/pingcap/tidb/util/chunk"
)

// columnBufferAllocator is used to allocate and release column buffer in vectorized evaluation.
type columnBufferAllocator interface {
	// get allocates a column. The allocator is not responsible for initializing the column, so please initialize it before using.
	get() (*chunk.Column, error)
	// put releases a column buffer.
	put(buf *chunk.Column)
	// MemoryUsage return the memory usage of columnBufferAllocator
	MemoryUsage() int64
}

// localColumnPool implements columnBufferAllocator interface.
// It works like a concurrency-safe deque which is implemented by lock-free sync.Pool.
type localColumnPool struct {
	sync.Pool
}

func newLocalColumnPool() *localColumnPool {
	newColumn := chunk.NewColumn(types.NewFieldType(mysql.TypeLonglong), chunk.InitialCapacity)
	return &localColumnPool{
		sync.Pool{
			New: func() interface{} {
				return newColumn.CopyConstruct(nil)
			},
		},
	}
}

var globalColumnAllocator = newLocalColumnPool()

// GetColumn allocates a column. The allocator is not responsible for initializing the column, so please initialize it before using.
func GetColumn(_ types.EvalType, _ int) (*chunk.Column, error) {
	return globalColumnAllocator.get()
}

// PutColumn releases a column buffer.
func PutColumn(buf *chunk.Column) {
	globalColumnAllocator.put(buf)
}

func (r *localColumnPool) get() (*chunk.Column, error) {
	col, ok := r.Pool.Get().(*chunk.Column)
	if !ok {
		return nil, errors.New("unexpected object in localColumnPool")
	}
	return col, nil
}

func (r *localColumnPool) put(col *chunk.Column) {
	r.Pool.Put(col)
}

const emptyLocalColumnPoolSize = int64(unsafe.Sizeof(localColumnPool{}))

func (r *localColumnPool) MemoryUsage() (sum int64) {
	return emptyLocalColumnPoolSize
}

// vecEvalIntByRows uses the non-vectorized(row-based) interface `evalInt` to eval the expression.
func vecEvalIntByRows(sig builtinFunc, input *chunk.Chunk, result *chunk.Column) error {
	n := input.NumRows()
	result.ResizeInt64(n, false)
	i64s := result.Int64s()
	for i := 0; i < n; i++ {
		res, isNull, err := sig.evalInt(input.GetRow(i))
		if err != nil {
			return err
		}
		result.SetNull(i, isNull)
		i64s[i] = res
	}
	return nil
}

// vecEvalStringByRows uses the non-vectorized(row-based) interface `evalString` to eval the expression.
func vecEvalStringByRows(sig builtinFunc, input *chunk.Chunk, result *chunk.Column) error {
	n := input.NumRows()
	result.ReserveString(n)
	for i := 0; i < n; i++ {
		res, isNull, err := sig.evalString(input.GetRow(i))
		if err != nil {
			return err
		}
		if isNull {
			result.AppendNull()
			continue
		}
		result.AppendString(res)
	}
	return nil
}

相关信息

tidb 源码目录

相关文章

tidb builtin 源码

tidb builtin_arithmetic 源码

tidb builtin_arithmetic_vec 源码

tidb builtin_cast 源码

tidb builtin_cast_vec 源码

tidb builtin_compare 源码

tidb builtin_compare_vec 源码

tidb builtin_compare_vec_generated 源码

tidb builtin_control 源码

tidb builtin_control_vec_generated 源码

0  赞