Skip to content

Commit 841cdd3

Browse files
authored
perf: add searchHint to getSeriesIndex (#4286)
* perf: add searchHint to getSeriesIndex * move searchHint to seriesIDRowsRewriter * add comments and unit tests * remove the second loop and needless tests * fix unit test
1 parent 6d19e2e commit 841cdd3

File tree

3 files changed

+77
-5
lines changed

3 files changed

+77
-5
lines changed

pkg/phlaredb/profile_store.go

Lines changed: 5 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -516,6 +516,7 @@ type seriesIDRowsRewriter struct {
516516
parquet.Rows
517517
pos int64
518518
seriesIndexes rowRangesWithSeriesIndex
519+
searchHint int // speed up getSeriesIndex()
519520
}
520521

521522
func (r *seriesIDRowsRewriter) SeekToRow(pos int64) error {
@@ -540,13 +541,14 @@ func (r *seriesIDRowsRewriter) ReadRows(rows []parquet.Row) (int, error) {
540541
if err != nil {
541542
return n, err
542543
}
543-
544+
// sh for next call of getSeriesIndex
545+
sh := r.searchHint
544546
for pos, row := range rows[:n] {
545547
// actual row num
546548
rowNum := r.pos + int64(pos)
547-
row[colIdxSeriesIndex] = parquet.ValueOf(r.seriesIndexes.getSeriesIndex(rowNum)).Level(0, 0, colIdxSeriesIndex)
549+
row[colIdxSeriesIndex] = parquet.ValueOf(r.seriesIndexes.getSeriesIndex(rowNum, &sh)).Level(0, 0, colIdxSeriesIndex)
548550
}
549-
551+
r.searchHint = sh
550552
r.pos += int64(n)
551553

552554
return n, nil

pkg/phlaredb/profile_test.go

Lines changed: 63 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -279,3 +279,66 @@ func TestProfileIndex_Add_OutOfOrder(t *testing.T) {
279279
require.Equal(t, []int64{20, 50, 80, 100, 110}, tsOrder)
280280

281281
}
282+
283+
func Test_rowRangesWithSeriesIndex_getSeriesIndex(t *testing.T) {
284+
testCases := []struct {
285+
name string
286+
ranges rowRangesWithSeriesIndex
287+
rowNum int64
288+
searchHint int
289+
expectSeriesIndex uint32
290+
expectPanic bool
291+
}{
292+
{
293+
name: "hit 1",
294+
ranges: rowRangesWithSeriesIndex{
295+
{rowRange: &rowRange{rowNum: 0, length: 5}, seriesIndex: 1},
296+
{rowRange: &rowRange{rowNum: 5, length: 5}, seriesIndex: 2},
297+
},
298+
rowNum: 4,
299+
searchHint: 0,
300+
expectSeriesIndex: 1,
301+
},
302+
{
303+
name: "hit 2",
304+
ranges: rowRangesWithSeriesIndex{
305+
{rowRange: &rowRange{rowNum: 0, length: 5}, seriesIndex: 1},
306+
{rowRange: &rowRange{rowNum: 5, length: 5}, seriesIndex: 2},
307+
},
308+
rowNum: 6,
309+
searchHint: 1,
310+
expectSeriesIndex: 2,
311+
},
312+
{
313+
name: "nil rowRange skipped",
314+
ranges: rowRangesWithSeriesIndex{
315+
{rowRange: nil, seriesIndex: 1},
316+
{rowRange: &rowRange{rowNum: 10, length: 5}, seriesIndex: 2},
317+
},
318+
rowNum: 12,
319+
searchHint: 0,
320+
expectSeriesIndex: 2,
321+
},
322+
{
323+
name: "not found panics",
324+
ranges: rowRangesWithSeriesIndex{{rowRange: &rowRange{rowNum: 0, length: 2}, seriesIndex: 1}},
325+
rowNum: 10,
326+
searchHint: 0,
327+
expectPanic: true,
328+
},
329+
}
330+
331+
for _, tc := range testCases {
332+
t.Run(tc.name, func(t *testing.T) {
333+
searchHint := tc.searchHint
334+
if tc.expectPanic {
335+
assert.Panics(t, func() {
336+
_ = tc.ranges.getSeriesIndex(tc.rowNum, &searchHint)
337+
})
338+
} else {
339+
idx := tc.ranges.getSeriesIndex(tc.rowNum, &searchHint)
340+
assert.Equal(t, tc.expectSeriesIndex, idx)
341+
}
342+
})
343+
}
344+
}

pkg/phlaredb/profiles.go

Lines changed: 9 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -40,13 +40,20 @@ type rowRangeWithSeriesIndex struct {
4040
// those need to be strictly ordered
4141
type rowRangesWithSeriesIndex []rowRangeWithSeriesIndex
4242

43-
func (s rowRangesWithSeriesIndex) getSeriesIndex(rowNum int64) uint32 {
44-
for _, rg := range s {
43+
// getSeriesIndex returns the series index for a given row number.
44+
// searchHint is the hint for the index to start searching from, it should be passed to next call of this function.
45+
func (s rowRangesWithSeriesIndex) getSeriesIndex(rowNum int64, searchHint *int) uint32 {
46+
if *searchHint < 0 || *searchHint >= len(s) {
47+
*searchHint = 0
48+
}
49+
for i := *searchHint; i < len(s); i++ {
50+
rg := s[i]
4551
// it is possible that the series is not existing
4652
if rg.rowRange == nil {
4753
continue
4854
}
4955
if rg.rowNum <= rowNum && rg.rowNum+int64(rg.length) > rowNum {
56+
*searchHint = i
5057
return rg.seriesIndex
5158
}
5259
}

0 commit comments

Comments
 (0)