dynamically size bloom filters
This commit is contained in:
parent
5639261e44
commit
cae5ddce88
@ -17,7 +17,7 @@ type LiveSet interface {
|
|||||||
var markBytes = []byte{}
|
var markBytes = []byte{}
|
||||||
|
|
||||||
type LiveSetEnv interface {
|
type LiveSetEnv interface {
|
||||||
NewLiveSet(name string) (LiveSet, error)
|
NewLiveSet(name string, sizeHint int64) (LiveSet, error)
|
||||||
Close() error
|
Close() error
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -30,14 +30,19 @@ func NewBloomLiveSetEnv() (*BloomLiveSetEnv, error) {
|
|||||||
return &BloomLiveSetEnv{}, nil
|
return &BloomLiveSetEnv{}, nil
|
||||||
}
|
}
|
||||||
|
|
||||||
func (e *BloomLiveSetEnv) NewLiveSet(name string) (LiveSet, error) {
|
func (e *BloomLiveSetEnv) NewLiveSet(name string, sizeHint int64) (LiveSet, error) {
|
||||||
|
size := int64(BloomFilterSize)
|
||||||
|
for size < sizeHint {
|
||||||
|
size += BloomFilterSize
|
||||||
|
}
|
||||||
|
|
||||||
salt := make([]byte, 4)
|
salt := make([]byte, 4)
|
||||||
_, err := rand.Read(salt) //nolint
|
_, err := rand.Read(salt) //nolint
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return nil, xerrors.Errorf("error reading salt: %w", err)
|
return nil, xerrors.Errorf("error reading salt: %w", err)
|
||||||
}
|
}
|
||||||
|
|
||||||
bf, err := bbloom.New(float64(BloomFilterSize), float64(BloomFilterProbability))
|
bf, err := bbloom.New(float64(size), float64(BloomFilterProbability))
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return nil, xerrors.Errorf("error creating bloom filter: %w", err)
|
return nil, xerrors.Errorf("error creating bloom filter: %w", err)
|
||||||
}
|
}
|
||||||
|
@ -35,7 +35,7 @@ func NewBoltLiveSetEnv(path string) (*BoltLiveSetEnv, error) {
|
|||||||
return &BoltLiveSetEnv{db: db}, nil
|
return &BoltLiveSetEnv{db: db}, nil
|
||||||
}
|
}
|
||||||
|
|
||||||
func (e *BoltLiveSetEnv) NewLiveSet(name string) (LiveSet, error) {
|
func (e *BoltLiveSetEnv) NewLiveSet(name string, hint int64) (LiveSet, error) {
|
||||||
bucketId := []byte(name)
|
bucketId := []byte(name)
|
||||||
err := e.db.Update(func(tx *bolt.Tx) error {
|
err := e.db.Update(func(tx *bolt.Tx) error {
|
||||||
_, err := tx.CreateBucketIfNotExists(bucketId)
|
_, err := tx.CreateBucketIfNotExists(bucketId)
|
||||||
|
@ -57,7 +57,7 @@ func NewLMDBLiveSetEnv(path string) (*LMDBLiveSetEnv, error) {
|
|||||||
return &LMDBLiveSetEnv{env: env}, nil
|
return &LMDBLiveSetEnv{env: env}, nil
|
||||||
}
|
}
|
||||||
|
|
||||||
func (e *LMDBLiveSetEnv) NewLiveSet(name string) (LiveSet, error) {
|
func (e *LMDBLiveSetEnv) NewLiveSet(name string, hint int64) (LiveSet, error) {
|
||||||
return NewLMDBLiveSet(e.env, name+".lmdb")
|
return NewLMDBLiveSet(e.env, name+".lmdb")
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -75,6 +75,8 @@ type SplitStore struct {
|
|||||||
snoop TrackingStore
|
snoop TrackingStore
|
||||||
|
|
||||||
env LiveSetEnv
|
env LiveSetEnv
|
||||||
|
|
||||||
|
liveSetSize int64
|
||||||
}
|
}
|
||||||
|
|
||||||
var _ bstore.Blockstore = (*SplitStore)(nil)
|
var _ bstore.Blockstore = (*SplitStore)(nil)
|
||||||
@ -328,6 +330,15 @@ func (s *SplitStore) HeadChange(revert, apply []*types.TipSet) error {
|
|||||||
|
|
||||||
// Compaction/GC Algorithm
|
// Compaction/GC Algorithm
|
||||||
func (s *SplitStore) compact() {
|
func (s *SplitStore) compact() {
|
||||||
|
if s.liveSetSize == 0 {
|
||||||
|
start := time.Now()
|
||||||
|
log.Info("estimating live set size")
|
||||||
|
s.estimateLiveSetSize()
|
||||||
|
log.Infow("estimating live set size done", "took", time.Since(start), "size", s.liveSetSize)
|
||||||
|
} else {
|
||||||
|
log.Infow("current live set size estimate", "size", s.liveSetSize)
|
||||||
|
}
|
||||||
|
|
||||||
if s.fullCompaction {
|
if s.fullCompaction {
|
||||||
s.compactFull()
|
s.compactFull()
|
||||||
} else {
|
} else {
|
||||||
@ -335,6 +346,24 @@ func (s *SplitStore) compact() {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func (s *SplitStore) estimateLiveSetSize() {
|
||||||
|
s.mx.Lock()
|
||||||
|
curTs := s.curTs
|
||||||
|
s.mx.Unlock()
|
||||||
|
|
||||||
|
s.liveSetSize = 0
|
||||||
|
err := s.cs.WalkSnapshot(context.Background(), curTs, 1, s.skipOldMsgs, s.skipMsgReceipts,
|
||||||
|
func(cid cid.Cid) error {
|
||||||
|
s.liveSetSize++
|
||||||
|
return nil
|
||||||
|
})
|
||||||
|
|
||||||
|
if err != nil {
|
||||||
|
// TODO do something better here
|
||||||
|
panic(err)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
func (s *SplitStore) compactSimple() {
|
func (s *SplitStore) compactSimple() {
|
||||||
s.mx.Lock()
|
s.mx.Lock()
|
||||||
curTs := s.curTs
|
curTs := s.curTs
|
||||||
@ -344,7 +373,7 @@ func (s *SplitStore) compactSimple() {
|
|||||||
|
|
||||||
log.Infow("running simple compaction", "currentEpoch", curTs.Height(), "baseEpoch", s.baseEpoch, "coldEpoch", coldEpoch)
|
log.Infow("running simple compaction", "currentEpoch", curTs.Height(), "baseEpoch", s.baseEpoch, "coldEpoch", coldEpoch)
|
||||||
|
|
||||||
coldSet, err := s.env.NewLiveSet("cold")
|
coldSet, err := s.env.NewLiveSet("cold", s.liveSetSize)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
// TODO do something better here
|
// TODO do something better here
|
||||||
panic(err)
|
panic(err)
|
||||||
@ -361,8 +390,10 @@ func (s *SplitStore) compactSimple() {
|
|||||||
panic(err)
|
panic(err)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
count := int64(0)
|
||||||
err = s.cs.WalkSnapshot(context.Background(), coldTs, 1, s.skipOldMsgs, s.skipMsgReceipts,
|
err = s.cs.WalkSnapshot(context.Background(), coldTs, 1, s.skipOldMsgs, s.skipMsgReceipts,
|
||||||
func(cid cid.Cid) error {
|
func(cid cid.Cid) error {
|
||||||
|
count++
|
||||||
return coldSet.Mark(cid)
|
return coldSet.Mark(cid)
|
||||||
})
|
})
|
||||||
|
|
||||||
@ -371,6 +402,10 @@ func (s *SplitStore) compactSimple() {
|
|||||||
panic(err)
|
panic(err)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if count > s.liveSetSize {
|
||||||
|
s.liveSetSize = count
|
||||||
|
}
|
||||||
|
|
||||||
log.Infow("marking done", "took", time.Since(startMark))
|
log.Infow("marking done", "took", time.Since(startMark))
|
||||||
|
|
||||||
// 2. move cold unreachable objects to the coldstore
|
// 2. move cold unreachable objects to the coldstore
|
||||||
@ -519,14 +554,14 @@ func (s *SplitStore) compactFull() {
|
|||||||
|
|
||||||
// create two live sets, one for marking the cold finality region
|
// create two live sets, one for marking the cold finality region
|
||||||
// and one for marking the hot region
|
// and one for marking the hot region
|
||||||
hotSet, err := s.env.NewLiveSet("hot")
|
hotSet, err := s.env.NewLiveSet("hot", s.liveSetSize)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
// TODO do something better here
|
// TODO do something better here
|
||||||
panic(err)
|
panic(err)
|
||||||
}
|
}
|
||||||
defer hotSet.Close() //nolint:errcheck
|
defer hotSet.Close() //nolint:errcheck
|
||||||
|
|
||||||
coldSet, err := s.env.NewLiveSet("cold")
|
coldSet, err := s.env.NewLiveSet("cold", s.liveSetSize)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
// TODO do something better here
|
// TODO do something better here
|
||||||
panic(err)
|
panic(err)
|
||||||
@ -538,8 +573,10 @@ func (s *SplitStore) compactFull() {
|
|||||||
startMark := time.Now()
|
startMark := time.Now()
|
||||||
|
|
||||||
// Phase 1a: mark all reachable CIDs in the hot range
|
// Phase 1a: mark all reachable CIDs in the hot range
|
||||||
|
count := int64(0)
|
||||||
err = s.cs.WalkSnapshot(context.Background(), curTs, epoch-coldEpoch, s.skipOldMsgs, s.skipMsgReceipts,
|
err = s.cs.WalkSnapshot(context.Background(), curTs, epoch-coldEpoch, s.skipOldMsgs, s.skipMsgReceipts,
|
||||||
func(cid cid.Cid) error {
|
func(cid cid.Cid) error {
|
||||||
|
count++
|
||||||
return hotSet.Mark(cid)
|
return hotSet.Mark(cid)
|
||||||
})
|
})
|
||||||
|
|
||||||
@ -548,6 +585,10 @@ func (s *SplitStore) compactFull() {
|
|||||||
panic(err)
|
panic(err)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if count > s.liveSetSize {
|
||||||
|
s.liveSetSize = count
|
||||||
|
}
|
||||||
|
|
||||||
// Phase 1b: mark all reachable CIDs in the cold range
|
// Phase 1b: mark all reachable CIDs in the cold range
|
||||||
coldTs, err := s.cs.GetTipsetByHeight(context.Background(), coldEpoch, curTs, true)
|
coldTs, err := s.cs.GetTipsetByHeight(context.Background(), coldEpoch, curTs, true)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
@ -555,8 +596,10 @@ func (s *SplitStore) compactFull() {
|
|||||||
panic(err)
|
panic(err)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
count = 0
|
||||||
err = s.cs.WalkSnapshot(context.Background(), coldTs, CompactionCold, s.skipOldMsgs, s.skipMsgReceipts,
|
err = s.cs.WalkSnapshot(context.Background(), coldTs, CompactionCold, s.skipOldMsgs, s.skipMsgReceipts,
|
||||||
func(cid cid.Cid) error {
|
func(cid cid.Cid) error {
|
||||||
|
count++
|
||||||
return coldSet.Mark(cid)
|
return coldSet.Mark(cid)
|
||||||
})
|
})
|
||||||
|
|
||||||
@ -565,6 +608,10 @@ func (s *SplitStore) compactFull() {
|
|||||||
panic(err)
|
panic(err)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if count > s.liveSetSize {
|
||||||
|
s.liveSetSize = count
|
||||||
|
}
|
||||||
|
|
||||||
log.Infow("marking done", "took", time.Since(startMark))
|
log.Infow("marking done", "took", time.Since(startMark))
|
||||||
|
|
||||||
// Phase 2: sweep cold objects:
|
// Phase 2: sweep cold objects:
|
||||||
|
Loading…
Reference in New Issue
Block a user