From e9d096ae6b1ca62167e914b79ac8d9a6a1bc3e9b Mon Sep 17 00:00:00 2001 From: Anthony Romano Date: Wed, 5 Jul 2017 17:23:19 -0700 Subject: [PATCH] mvcc: don't allocate end revision while computing range Use 'nil' since it's only reading a single key. Also preallocates the result slice based on limit / number of revisions fetched. Fixes #8208 --- mvcc/kvstore.go | 13 ------------- mvcc/kvstore_test.go | 5 +++-- mvcc/kvstore_txn.go | 22 +++++++++++----------- 3 files changed, 14 insertions(+), 26 deletions(-) diff --git a/mvcc/kvstore.go b/mvcc/kvstore.go index ad9e7f61842..34fc761723c 100644 --- a/mvcc/kvstore.go +++ b/mvcc/kvstore.go @@ -445,16 +445,3 @@ func appendMarkTombstone(b []byte) []byte { func isTombstone(b []byte) bool { return len(b) == markedRevBytesLen && b[markBytePosition] == markTombstone } - -// revBytesRange returns the range of revision bytes at -// the given revision. -func revBytesRange(rev revision) (start, end []byte) { - start = newRevBytes() - revToBytes(rev, start) - - end = newRevBytes() - endRev := revision{main: rev.main, sub: rev.sub + 1} - revToBytes(endRev, end) - - return start, end -} diff --git a/mvcc/kvstore_test.go b/mvcc/kvstore_test.go index 6b73a9426f5..e3970af7c7d 100644 --- a/mvcc/kvstore_test.go +++ b/mvcc/kvstore_test.go @@ -217,9 +217,10 @@ func TestStoreRange(t *testing.T) { t.Errorf("#%d: rev = %d, want %d", i, ret.Rev, wrev) } - wstart, wend := revBytesRange(tt.idxr.revs[0]) + wstart := newRevBytes() + revToBytes(tt.idxr.revs[0], wstart) wact := []testutil.Action{ - {"range", []interface{}{keyBucketName, wstart, wend, int64(0)}}, + {"range", []interface{}{keyBucketName, wstart, []byte(nil), int64(0)}}, } if g := b.tx.Action(); !reflect.DeepEqual(g, wact) { t.Errorf("#%d: tx action = %+v, want %+v", i, g, wact) diff --git a/mvcc/kvstore_txn.go b/mvcc/kvstore_txn.go index ae89d0f7124..b0832fa9e34 100644 --- a/mvcc/kvstore_txn.go +++ b/mvcc/kvstore_txn.go @@ -128,22 +128,22 @@ func (tr *storeTxnRead) rangeKeys(key, end []byte, curRev int64, ro RangeOptions return &RangeResult{KVs: nil, Count: len(revpairs), Rev: curRev}, nil } - var kvs []mvccpb.KeyValue - for _, revpair := range revpairs { - start, end := revBytesRange(revpair) - _, vs := tr.tx.UnsafeRange(keyBucketName, start, end, 0) + limit := int(ro.Limit) + if limit <= 0 || limit > len(revpairs) { + limit = len(revpairs) + } + + kvs := make([]mvccpb.KeyValue, limit) + revBytes := newRevBytes() + for i, revpair := range revpairs[:len(kvs)] { + revToBytes(revpair, revBytes) + _, vs := tr.tx.UnsafeRange(keyBucketName, revBytes, nil, 0) if len(vs) != 1 { plog.Fatalf("range cannot find rev (%d,%d)", revpair.main, revpair.sub) } - - var kv mvccpb.KeyValue - if err := kv.Unmarshal(vs[0]); err != nil { + if err := kvs[i].Unmarshal(vs[0]); err != nil { plog.Fatalf("cannot unmarshal event: %v", err) } - kvs = append(kvs, kv) - if ro.Limit > 0 && len(kvs) >= int(ro.Limit) { - break - } } return &RangeResult{KVs: kvs, Count: len(revpairs), Rev: curRev}, nil }