pingcap / pingcap/tidb

optimize BCE

Open
#34,669 0 comments 1 reaction 0 assignees View on GitHub
type/enhancement
Dominant language
Go
Stars
40.5k
Forks
6.2k
PR merge metrics
PR metrics pending

Description

## Enhancement

Go is a memory safe language. In array/slice element indexing and subslice operations, Go runtime will check whether or not the involved indexes are out of range. If an index is out of range, a panic will be produced to prevent the invalid index from doing harm. This is called bounds check. Bounds checks make our code run safely, on the other hand, they also make our code run a little slower.

Since Go Toolchain 1.7, the standard Go compiler has used a new compiler backend, which based on SSA (static single-assignment form). SSA helps Go compilers effectively use optimizations like [BCE](https://en.wikipedia.org/wiki/Bounds-checking_elimination) (bounds check elimination) and [CSE](https://en.wikipedia.org/wiki/Common_subexpression_elimination) (common subexpression elimination). BCE can avoid some unnecessary bounds checks, and CSE can avoid some duplicate calculations, so that the standard Go compiler can generate more efficient programs. Sometimes the improvement effects of these optimizations are obvious.

This article will list some examples to show how BCE works with the standard Go compiler 1.7+.

For Go Toolchain 1.7+, we can use -gcflags="-d=ssa/check_bce/debug=1" compiler flag to show which code lines still need bounds checks.

### Example

```diff
diff --git a/expression/builtin_time_vec.go b/expression/builtin_time_vec.go
index b6bab705d27bd..1db9d3436cc75 100644
--- a/expression/builtin_time_vec.go
+++ b/expression/builtin_time_vec.go
@@ -139,8 +139,10 @@ func (b *builtinFromUnixTime2ArgSig) vecEvalString(input *chunk.Chunk, result *c
result.ReserveString(n)
ds := buf1.Decimals()
fsp := b.tp.GetDecimal()
+ _ = buf1.NullBitmap[(n-1)/8]
+ _ = buf2.NullBitmap[(n-1)/8]
for i := 0; i < n; i++ {
- if buf1.IsNull(i) || buf2.IsNull(i) {
+ if buf1.NullBitmap[i/8]&buf2.NullBitmap[i/8]&(1<<(uint(i)&7)) == 0 {
result.AppendNull()
continue
}
```

```
make vectorized-bench VB_FILE=Time VB_FUNC=builtinFromUnixTime2ArgSig
```

Before

```go
goos: darwin
goarch: amd64
pkg: github.com/pingcap/tidb/expression
cpu: Intel(R) Core(TM) i9-9880H CPU @ 2.30GHz
BenchmarkVectorizedBuiltinTimeFuncGenerated
BenchmarkVectorizedBuiltinTimeFuncGenerated-16 1000000000 0.3045 ns/op 0 B/op 0 allocs/op
BenchmarkVectorizedBuiltinTimeFunc
BenchmarkVectorizedBuiltinTimeFunc-16 1000000000 0.06184 ns/op 0 B/op 0 allocs/op
PASS
ok github.com/pingcap/tidb/expression 7.986s
```

After

```
goos: darwin
goarch: amd64
pkg: github.com/pingcap/tidb/expression
cpu: Intel(R) Core(TM) i9-9880H CPU @ 2.30GHz
BenchmarkVectorizedBuiltinTimeFuncGenerated
BenchmarkVectorizedBuiltinTimeFuncGenerated-16 1000000000 0.2601 ns/op 0 B/op 0 allocs/op
BenchmarkVectorizedBuiltinTimeFunc
BenchmarkVectorizedBuiltinTimeFunc-16 1000000000 0.05196 ns/op 0 B/op 0 allocs/op
PASS
ok github.com/pingcap/tidb/expression 5.989s
```

**17% performance improvement**

Contributor guide

Open the contributing guide

Assessment

This issue has not been assessed yet.

Get new issues in your inbox

A short digest of beginner-friendly GitHub issues.