From 3ef25e4a161579ae3ae1efa1628e2245412480ad Mon Sep 17 00:00:00 2001 From: Seebs Date: Fri, 24 Sep 2021 15:31:33 -0500 Subject: [PATCH] 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. --- executor.go | 22 +++++++++++----------- 1 file changed, 11 insertions(+), 11 deletions(-) diff --git a/executor.go b/executor.go index a46ca6d2a..ac9f4455e 100644 --- a/executor.go +++ b/executor.go @@ -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.