blob: 7d04c562bdecb0cb81fa909d66bb8edfaaede024 [file]
// Licensed to the Apache Software Foundation (ASF) under one
// or more contributor license agreements. See the NOTICE file
// distributed with this work for additional information
// regarding copyright ownership. The ASF licenses this file
// to you 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 array_test
import (
"fmt"
"testing"
"github.com/apache/arrow-go/v18/arrow"
"github.com/apache/arrow-go/v18/arrow/array"
"github.com/apache/arrow-go/v18/arrow/memory"
)
var benchmarkUnionEqualResult bool
func BenchmarkUnionEqual(b *testing.B) {
const rows = 65536
for _, mode := range []string{"sparse", "dense"} {
for _, pattern := range []string{"one-type", "runs-64", "alternating"} {
for _, mismatch := range []bool{false, true} {
for _, comparison := range []struct {
name string
fn func(arrow.Array, arrow.Array) bool
}{
{name: "equal", fn: array.Equal},
{name: "approx", fn: func(left, right arrow.Array) bool {
return array.ApproxEqual(left, right)
}},
} {
name := fmt.Sprintf("%s/%s/%s/%s", mode, pattern, comparison.name, unionEqualBenchmarkMismatchName(mismatch))
b.Run(name, func(b *testing.B) {
left := makeUnionEqualBenchmarkArray(b, mode, pattern, rows, false)
right := makeUnionEqualBenchmarkArray(b, mode, pattern, rows, mismatch)
defer left.Release()
defer right.Release()
b.ReportAllocs()
b.SetBytes(int64(rows))
b.ResetTimer()
for i := 0; i < b.N; i++ {
benchmarkUnionEqualResult = comparison.fn(left, right)
}
})
}
}
}
}
}
func unionEqualBenchmarkMismatchName(mismatch bool) string {
if mismatch {
return "mismatch-last"
}
return "equal"
}
func makeUnionEqualBenchmarkArray(b *testing.B, mode, pattern string, rows int, mismatch bool) arrow.Array {
b.Helper()
typeIDs := make([]int8, rows)
offsets := make([]int32, rows)
sparseInts := make([]int32, rows)
sparseStrings := make([]string, rows)
denseInts := make([]int32, 0, rows)
denseStrings := make([]string, 0, rows)
childOffsets := [2]int32{}
for i := 0; i < rows; i++ {
childID := unionEqualBenchmarkChildID(pattern, i)
typeIDs[i] = int8(childID)
if mode == "sparse" {
sparseInts[i] = int32(i)
sparseStrings[i] = fmt.Sprintf("value-%d", i)
if mismatch && i == rows-1 {
if childID == 0 {
sparseInts[i]++
} else {
sparseStrings[i] = "different"
}
}
continue
}
offsets[i] = childOffsets[childID]
if childID == 0 {
value := int32(i)
if mismatch && i == rows-1 {
value++
}
denseInts = append(denseInts, value)
} else {
value := fmt.Sprintf("value-%d", i)
if mismatch && i == rows-1 {
value = "different"
}
denseStrings = append(denseStrings, value)
}
childOffsets[childID]++
}
typeIDsArray := makeUnionEqualBenchmarkInt8Array(b, typeIDs)
defer typeIDsArray.Release()
if mode == "sparse" {
intArray := makeUnionEqualBenchmarkInt32Array(b, sparseInts)
defer intArray.Release()
stringArray := makeUnionEqualBenchmarkStringArray(b, sparseStrings)
defer stringArray.Release()
result, err := array.NewSparseUnionFromArrays(typeIDsArray, []arrow.Array{intArray, stringArray})
if err != nil {
b.Fatal(err)
}
return result
}
offsetsArray := makeUnionEqualBenchmarkInt32Array(b, offsets)
defer offsetsArray.Release()
intArray := makeUnionEqualBenchmarkInt32Array(b, denseInts)
defer intArray.Release()
stringArray := makeUnionEqualBenchmarkStringArray(b, denseStrings)
defer stringArray.Release()
result, err := array.NewDenseUnionFromArrays(typeIDsArray, offsetsArray, []arrow.Array{intArray, stringArray})
if err != nil {
b.Fatal(err)
}
return result
}
func unionEqualBenchmarkChildID(pattern string, index int) int {
switch pattern {
case "one-type":
return 0
case "runs-64":
return (index / 64) % 2
case "alternating":
return index % 2
default:
panic("unsupported union equality benchmark pattern")
}
}
func makeUnionEqualBenchmarkInt8Array(b *testing.B, values []int8) arrow.Array {
b.Helper()
builder := array.NewInt8Builder(memory.DefaultAllocator)
builder.AppendValues(values, nil)
result := builder.NewInt8Array()
builder.Release()
return result
}
func makeUnionEqualBenchmarkInt32Array(b *testing.B, values []int32) arrow.Array {
b.Helper()
builder := array.NewInt32Builder(memory.DefaultAllocator)
builder.AppendValues(values, nil)
result := builder.NewInt32Array()
builder.Release()
return result
}
func makeUnionEqualBenchmarkStringArray(b *testing.B, values []string) arrow.Array {
b.Helper()
builder := array.NewStringBuilder(memory.DefaultAllocator)
builder.AppendValues(values, nil)
result := builder.NewStringArray()
builder.Release()
return result
}