Skip to content

Commit 302a192

Browse files
authored
Merge pull request #3850 from parca-dev/filter-perf
pkg/query: Improve filter performance
2 parents 57e1275 + fa67ec6 commit 302a192

File tree

1 file changed

+23
-10
lines changed

1 file changed

+23
-10
lines changed

pkg/query/columnquery.go

Lines changed: 23 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -279,13 +279,13 @@ func FilterProfileData(
279279

280280
// We want to filter by function name case-insensitive, so we need to lowercase the query.
281281
// We lower case the query here, so we don't have to do it for every sample.
282-
filterQuery = strings.ToLower(filterQuery)
282+
filterQueryBytes := []byte(strings.ToLower(filterQuery))
283283
res := make([]arrow.Record, 0, len(records))
284284
allValues := int64(0)
285285
allFiltered := int64(0)
286286

287287
for _, r := range records {
288-
filteredRecord, valueSum, filteredSum, err := filterRecord(ctx, tracer, pool, r, filterQuery)
288+
filteredRecord, valueSum, filteredSum, err := filterRecord(ctx, tracer, pool, r, filterQueryBytes)
289289
if err != nil {
290290
return nil, 0, fmt.Errorf("filter record: %w", err)
291291
}
@@ -303,7 +303,7 @@ func filterRecord(
303303
tracer trace.Tracer,
304304
pool memory.Allocator,
305305
rec arrow.Record,
306-
filterQuery string,
306+
filterQueryBytes []byte,
307307
) (arrow.Record, int64, int64, error) {
308308
r := profile.NewRecordReader(rec)
309309

@@ -316,16 +316,29 @@ func filterRecord(
316316
w := profile.NewWriter(pool, labelNames)
317317
defer w.RecordBuilder.Release()
318318

319+
indexMatches := map[uint32]struct{}{}
320+
for i := 0; i < r.LineFunctionNameDict.Len(); i++ {
321+
if bytes.Contains(bytes.ToLower(r.LineFunctionNameDict.Value(i)), filterQueryBytes) {
322+
indexMatches[uint32(i)] = struct{}{}
323+
}
324+
}
325+
326+
if len(indexMatches) == 0 {
327+
return w.RecordBuilder.NewRecord(), math.Int64.Sum(r.Value), 0, nil
328+
}
329+
319330
for i := 0; i < int(rec.NumRows()); i++ {
320331
lOffsetStart, lOffsetEnd := r.Locations.ValueOffsets(i)
321332
keepRow := false
322-
for j := int(lOffsetStart); j < int(lOffsetEnd); j++ {
323-
llOffsetStart, llOffsetEnd := r.Lines.ValueOffsets(j)
324-
325-
for k := int(llOffsetStart); k < int(llOffsetEnd); k++ {
326-
if r.LineFunctionNameIndices.IsValid(k) && bytes.Contains(bytes.ToLower(r.LineFunctionNameDict.Value(int(r.LineFunctionNameIndices.Value(k)))), []byte(filterQuery)) {
327-
keepRow = true
328-
break
333+
if lOffsetStart < lOffsetEnd {
334+
firstStart, _ := r.Lines.ValueOffsets(int(lOffsetStart))
335+
_, lastEnd := r.Lines.ValueOffsets(int(lOffsetEnd - 1))
336+
for k := int(firstStart); k < int(lastEnd); k++ {
337+
if r.LineFunctionNameIndices.IsValid(k) {
338+
if _, ok := indexMatches[r.LineFunctionNameIndices.Value(k)]; ok {
339+
keepRow = true
340+
break
341+
}
329342
}
330343
}
331344
}

0 commit comments

Comments
 (0)