[#1685] metabase: Cache primary bucket
Some checks failed
Build / Build Components (push) Has been cancelled
OCI image / Build container images (push) Has been cancelled
Pre-commit hooks / Pre-commit (push) Has been cancelled
Tests and linters / Lint (push) Has been cancelled
Tests and linters / Tests (push) Has been cancelled
Tests and linters / Tests with -race (push) Has been cancelled
Tests and linters / Staticcheck (push) Has been cancelled
Tests and linters / gopls check (push) Has been cancelled
Tests and linters / Run gofumpt (push) Has been cancelled
Vulncheck / Vulncheck (push) Successful in 1m32s

```
goos: linux
goarch: amd64
pkg: git.frostfs.info/TrueCloudLab/frostfs-node/pkg/local_object_storage/metabase
cpu: 11th Gen Intel(R) Core(TM) i5-1135G7 @ 2.40GHz
                          │   expired    │               primary               │
                          │    sec/op    │    sec/op     vs base               │
Select/string_equal-8       3.529m ± 11%   3.689m ±  7%  +4.55% (p=0.023 n=10)
Select/string_not_equal-8   3.440m ±  7%   3.543m ± 13%       ~ (p=0.190 n=10)
Select/common_prefix-8      3.240m ±  6%   3.050m ±  5%  -5.85% (p=0.005 n=10)
Select/unknown-8            3.198m ±  6%   2.928m ±  8%  -8.44% (p=0.003 n=10)
geomean                     3.349m         3.287m        -1.84%

                          │   expired    │               primary               │
                          │     B/op     │     B/op      vs base               │
Select/string_equal-8       1.885Mi ± 0%   1.786Mi ± 0%  -5.23% (p=0.000 n=10)
Select/string_not_equal-8   1.885Mi ± 0%   1.786Mi ± 0%  -5.23% (p=0.000 n=10)
Select/common_prefix-8      1.885Mi ± 0%   1.786Mi ± 0%  -5.23% (p=0.000 n=10)
Select/unknown-8            1.877Mi ± 0%   1.779Mi ± 0%  -5.26% (p=0.000 n=10)
geomean                     1.883Mi        1.784Mi       -5.24%

                          │   expired   │              primary               │
                          │  allocs/op  │  allocs/op   vs base               │
Select/string_equal-8       46.04k ± 0%   43.04k ± 0%  -6.50% (p=0.000 n=10)
Select/string_not_equal-8   46.04k ± 0%   43.04k ± 0%  -6.50% (p=0.000 n=10)
Select/common_prefix-8      46.04k ± 0%   43.04k ± 0%  -6.50% (p=0.000 n=10)
Select/unknown-8            45.05k ± 0%   42.05k ± 0%  -6.65% (p=0.000 n=10)
geomean                     45.79k        42.79k       -6.54%
```

Signed-off-by: Evgenii Stratonikov <e.stratonikov@yadro.com>
This commit is contained in:
Evgenii Stratonikov 2025-03-20 10:23:26 +03:00 committed by Evgenii Stratonikov
parent 21bed3362c
commit eb9df85b98
3 changed files with 30 additions and 12 deletions

View file

@ -10,10 +10,14 @@ type bucketCache struct {
graveyard *bbolt.Bucket
garbage *bbolt.Bucket
expired map[cid.ID]*bbolt.Bucket
primary map[cid.ID]*bbolt.Bucket
}
func newBucketCache() *bucketCache {
return &bucketCache{expired: make(map[cid.ID]*bbolt.Bucket)}
return &bucketCache{
expired: make(map[cid.ID]*bbolt.Bucket),
primary: make(map[cid.ID]*bbolt.Bucket),
}
}
func getLockedBucket(bc *bucketCache, tx *bbolt.Tx) *bbolt.Bucket {
@ -55,6 +59,15 @@ func getExpiredBucket(bc *bucketCache, tx *bbolt.Tx, cnr cid.ID) *bbolt.Bucket {
return getMappedBucket(bc.expired, tx, objectToExpirationEpochBucketName, cnr)
}
func getPrimaryBucket(bc *bucketCache, tx *bbolt.Tx, cnr cid.ID) *bbolt.Bucket {
if bc == nil {
bucketName := make([]byte, bucketKeySize)
bucketName = primaryBucketName(cnr, bucketName)
return tx.Bucket(bucketName)
}
return getMappedBucket(bc.primary, tx, primaryBucketName, cnr)
}
func getMappedBucket(m map[cid.ID]*bbolt.Bucket, tx *bbolt.Tx, nameFunc func(cid.ID, []byte) []byte, cnr cid.ID) *bbolt.Bucket {
value, ok := m[cnr]
if ok {

View file

@ -88,8 +88,12 @@ func (db *DB) Get(ctx context.Context, prm GetPrm) (res GetRes, err error) {
}
func (db *DB) get(tx *bbolt.Tx, addr oid.Address, key []byte, checkStatus, raw bool, currEpoch uint64) (*objectSDK.Object, error) {
return db.getWithCache(nil, tx, addr, key, checkStatus, raw, currEpoch)
}
func (db *DB) getWithCache(bc *bucketCache, tx *bbolt.Tx, addr oid.Address, key []byte, checkStatus, raw bool, currEpoch uint64) (*objectSDK.Object, error) {
if checkStatus {
st, err := objectStatus(tx, addr, currEpoch)
st, err := objectStatusWithCache(bc, tx, addr, currEpoch)
if err != nil {
return nil, err
}
@ -109,12 +113,13 @@ func (db *DB) get(tx *bbolt.Tx, addr oid.Address, key []byte, checkStatus, raw b
bucketName := make([]byte, bucketKeySize)
// check in primary index
data := getFromBucket(tx, primaryBucketName(cnr, bucketName), key)
if len(data) != 0 {
return obj, obj.Unmarshal(data)
if b := getPrimaryBucket(bc, tx, cnr); b != nil {
if data := b.Get(key); len(data) != 0 {
return obj, obj.Unmarshal(data)
}
}
data = getFromBucket(tx, ecInfoBucketName(cnr, bucketName), key)
data := getFromBucket(tx, ecInfoBucketName(cnr, bucketName), key)
if len(data) != 0 {
return nil, getECInfoError(tx, cnr, data)
}

View file

@ -154,7 +154,7 @@ func (db *DB) selectObjects(tx *bbolt.Tx, cnr cid.ID, fs objectSDK.SearchFilters
continue // ignore removed objects
}
addr, match := db.matchSlowFilters(tx, addr, group.slowFilters, currEpoch)
addr, match := db.matchSlowFilters(bc, tx, addr, group.slowFilters, currEpoch)
if !match {
continue // ignore objects with unmatched slow filters
}
@ -452,13 +452,13 @@ func (db *DB) selectObjectID(
}
// matchSlowFilters return true if object header is matched by all slow filters.
func (db *DB) matchSlowFilters(tx *bbolt.Tx, addr oid.Address, f objectSDK.SearchFilters, currEpoch uint64) (oid.Address, bool) {
func (db *DB) matchSlowFilters(bc *bucketCache, tx *bbolt.Tx, addr oid.Address, f objectSDK.SearchFilters, currEpoch uint64) (oid.Address, bool) {
result := addr
if len(f) == 0 {
return result, true
}
obj, isECChunk, err := db.getObjectForSlowFilters(tx, addr, currEpoch)
obj, isECChunk, err := db.getObjectForSlowFilters(bc, tx, addr, currEpoch)
if err != nil {
return result, false
}
@ -516,9 +516,9 @@ func (db *DB) matchSlowFilters(tx *bbolt.Tx, addr oid.Address, f objectSDK.Searc
return result, true
}
func (db *DB) getObjectForSlowFilters(tx *bbolt.Tx, addr oid.Address, currEpoch uint64) (*objectSDK.Object, bool, error) {
func (db *DB) getObjectForSlowFilters(bc *bucketCache, tx *bbolt.Tx, addr oid.Address, currEpoch uint64) (*objectSDK.Object, bool, error) {
buf := make([]byte, addressKeySize)
obj, err := db.get(tx, addr, buf, false, false, currEpoch)
obj, err := db.getWithCache(bc, tx, addr, buf, false, false, currEpoch)
if err != nil {
var ecInfoError *objectSDK.ECInfoError
if errors.As(err, &ecInfoError) {
@ -528,7 +528,7 @@ func (db *DB) getObjectForSlowFilters(tx *bbolt.Tx, addr oid.Address, currEpoch
continue
}
addr.SetObject(objID)
obj, err = db.get(tx, addr, buf, true, false, currEpoch)
obj, err = db.getWithCache(bc, tx, addr, buf, true, false, currEpoch)
if err == nil {
return obj, true, nil
}