rework executor's per-shard union to use UnionInPlace

The actual code here is mostly jaffee's, but I've reworked it some.

This doesn't directly seem to be using UnionInPlace, but really it
is.

The actual logic inside (*Row).Union is a mess and probably silly
in a few ways, but hardly matters. The important part is that,
instead of calling it once per child as we get them, we gather
all of them at once and then call it on all of them. That gets
us a call to (*Row).Union that does a very elaborate dance to
compute a call to (*rowSegment).Union on the only segment present
in each of those rows, which then does a simpler thing to
call (*Bitmap).Union() with the first response as a receiver
and the rest as parameters, and THAT then ends up calling either
unionIntoTargetSingle() if there's only one other bitmap,
or using UnionInPlace on a Freeze() of the first bitmap, which
gets us (we hope) the benefits of the fancy UnionInPlace logic.

Every part of this is a reminder that we really need to replace
roaring and also the Row/rowSegment stuff some day.
This commit is contained in:
Seebs 2021-09-24 15:31:33 -05:00
parent e5479390b8
commit 3ef25e4a16

View file

@ -4750,25 +4750,25 @@ func (e *executor) executeIntersectShard(ctx context.Context, qcx *Qcx, index st
}
// executeUnionShard executes a union() call for a local shard.
func (e *executor) executeUnionShard(ctx context.Context, qcx *Qcx, index string, c *pql.Call, shard uint64) (_ *Row, err error) {
func (e *executor) executeUnionShard(ctx context.Context, qcx *Qcx, index string, c *pql.Call, shard uint64) (out *Row, err error) {
span, ctx := tracing.StartSpanFromContext(ctx, "Executor.executeUnionShard")
defer span.Finish()
other := NewRow()
if len(c.Children) == 0 {
return NewRow(), nil
}
if len(c.Children) == 1 {
return e.executeBitmapCallShard(ctx, qcx, index, c.Children[0], shard)
}
// we have at least two, so...
rows := make([]*Row, len(c.Children))
for i, input := range c.Children {
row, err := e.executeBitmapCallShard(ctx, qcx, index, input, shard)
rows[i], err = e.executeBitmapCallShard(ctx, qcx, index, input, shard)
if err != nil {
return nil, err
}
if i == 0 {
other = row
} else {
other = other.Union(row)
}
}
other.invalidateCount()
return other, nil
return rows[0].Union(rows[1:]...), nil
}
// executeXorShard executes a xor() call for a local shard.