Skip to content

Commit

Permalink
Add benchmark and fix list resizing
Browse files Browse the repository at this point in the history
  • Loading branch information
JAicewizard committed Sep 20, 2024
1 parent 8c4f21b commit c222d2c
Show file tree
Hide file tree
Showing 4 changed files with 117 additions and 8 deletions.
105 changes: 102 additions & 3 deletions appender_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -267,8 +267,8 @@ func TestAppenderNested(t *testing.T) {
L Map
}{L: Map{"foo": int32(1), "bar": int32(2)}},
}
rowsToAppend := make([]nestedDataRow, 10)
for i := 0; i < 10; i++ {
rowsToAppend := make([]nestedDataRow, 1000)
for i := 0; i < 1000; i++ {
rowsToAppend[i].ID = int64(i)
rowsToAppend[i].stringList = []string{"a", "b", "c"}
rowsToAppend[i].intList = []int32{1, 2, 3}
Expand Down Expand Up @@ -352,7 +352,7 @@ func TestAppenderNested(t *testing.T) {
i++
}

require.Equal(t, 10, i)
require.Equal(t, 1000, i)
require.NoError(t, res.Close())
cleanupAppender(t, c, con, a)
}
Expand Down Expand Up @@ -835,3 +835,102 @@ func TestAppenderWithJSON(t *testing.T) {
require.NoError(t, res.Close())
cleanupAppender(t, c, con, a)
}

func BenchmarkAppenderNested(b *testing.B) {
c, con, a := prepareAppender(b, `
CREATE TABLE test (
id BIGINT,
string_list VARCHAR[],
int_list INT[],
nested_int_list INT[][],
triple_nested_int_list INT[][][],
simple_struct STRUCT(A INT, B VARCHAR),
wrapped_struct STRUCT(N VARCHAR, M STRUCT(A INT, B VARCHAR)),
double_wrapped_struct STRUCT(
X VARCHAR,
Y STRUCT(
N VARCHAR,
M STRUCT(
A INT,
B VARCHAR
)
)
),
struct_list STRUCT(A INT, B VARCHAR)[],
struct_with_list STRUCT(L INT[]),
mix STRUCT(
A STRUCT(L VARCHAR[]),
B STRUCT(L INT[])[],
C STRUCT(L MAP(VARCHAR, INT))
),
mix_list STRUCT(
A STRUCT(L VARCHAR[]),
B STRUCT(L INT[])[],
C STRUCT(L MAP(VARCHAR, INT))
)[]
)
`)

ms := mixedStruct{
A: struct {
L []string
}{
[]string{"a", "b", "c"},
},
B: []struct {
L []int32
}{
{[]int32{1, 2, 3}},
},
C: struct {
L Map
}{L: Map{"foo": int32(1), "bar": int32(2)}},
}
// TODO: This crashes when set to 600?
const rows = 1000
rowsToAppend := make([]nestedDataRow, rows)
for i := 0; i < rows; i++ {
rowsToAppend[i].ID = int64(i)
rowsToAppend[i].stringList = []string{"a", "b", "c"}
rowsToAppend[i].intList = []int32{1, 2, 3}
rowsToAppend[i].nestedIntList = [][]int32{{1, 2, 3}, {4, 5, 6}}
rowsToAppend[i].tripleNestedIntList = [][][]int32{
{{1, 2, 3}, {4, 5, 6}},
{{7, 8, 9}, {10, 11, 12}},
}
rowsToAppend[i].simpleStruct = simpleStruct{A: 1, B: "foo"}
rowsToAppend[i].wrappedStruct = wrappedStruct{"wrapped", simpleStruct{1, "foo"}}
rowsToAppend[i].doubleWrappedStruct = doubleWrappedStruct{
"so much nesting",
wrappedStruct{
"wrapped",
simpleStruct{1, "foo"},
},
}
rowsToAppend[i].structList = []simpleStruct{{1, "a"}, {2, "b"}, {3, "c"}}
rowsToAppend[i].structWithList.L = []int32{6, 7, 8}
rowsToAppend[i].mix = ms
rowsToAppend[i].mixList = []mixedStruct{ms, ms}
}
b.ResetTimer()
for n := 0; n < b.N; n++ {
for _, row := range rowsToAppend {
require.NoError(b, a.AppendRow(
row.ID,
row.stringList,
row.intList,
row.nestedIntList,
row.tripleNestedIntList,
row.simpleStruct,
row.wrappedStruct,
row.doubleWrappedStruct,
row.structList,
row.structWithList,
row.mix,
row.mixList))
}
require.NoError(b, a.Flush())
}
b.StopTimer()
cleanupAppender(b, c, con, a)
}
2 changes: 1 addition & 1 deletion types_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -272,7 +272,7 @@ func BenchmarkTypes(b *testing.B) {
r = testTypes(b, c, a, expectedRows)
testTypesReset(b, c)
}

b.StopTimer()
// Ensure that the compiler does not eliminate the line by storing the result.
benchmarkTypesResult = r
cleanupAppender(b, c, con, a)
Expand Down
15 changes: 13 additions & 2 deletions vector.go
Original file line number Diff line number Diff line change
Expand Up @@ -99,6 +99,19 @@ func (vec *vector) init(logicalType C.duckdb_logical_type, colIdx int) error {
return nil
}

func (vec *vector) resizeListVector(newLength C.idx_t) {
C.duckdb_list_vector_reserve(vec.duckdbVector, newLength)
C.duckdb_list_vector_set_size(vec.duckdbVector, newLength)
vec.resetData()
}

func (vec *vector) resetData() {
vec.ptr = C.duckdb_vector_get_data(vec.duckdbVector)
for i := range vec.childVectors {
vec.childVectors[i].resetData()
}
}

func (vec *vector) initVectors(v C.duckdb_vector, writable bool) {
vec.duckdbVector = v
vec.ptr = C.duckdb_vector_get_data(v)
Expand All @@ -111,11 +124,9 @@ func (vec *vector) initVectors(v C.duckdb_vector, writable bool) {

func (vec *vector) getChildVectors(v C.duckdb_vector, writable bool) {
switch vec.Type {

case TYPE_LIST, TYPE_MAP:
child := C.duckdb_list_vector_get_child(v)
vec.childVectors[0].initVectors(child, writable)

case TYPE_STRUCT:
for i := 0; i < len(vec.childVectors); i++ {
child := C.duckdb_struct_vector_get_child(v, C.idx_t(i))
Expand Down
3 changes: 1 addition & 2 deletions vector_setters.go
Original file line number Diff line number Diff line change
Expand Up @@ -325,8 +325,7 @@ func setList[S any](vec *vector, rowIdx C.idx_t, val S) error {
setPrimitive(vec, rowIdx, listEntry)

newLength := C.idx_t(len(list)) + childVectorSize
C.duckdb_list_vector_set_size(vec.duckdbVector, newLength)
C.duckdb_list_vector_reserve(vec.duckdbVector, newLength)
vec.resizeListVector(newLength)

// Insert the values into the child vector.
childVector := &vec.childVectors[0]
Expand Down

0 comments on commit c222d2c

Please sign in to comment.