index: reduce size of compressed indexes

use the same index size for compressed and uncompressed indexes.
Otherwise, decoding the index of a compressed repository requires
significantly more memory.
This commit is contained in:
Michael Eischer 2024-05-20 00:34:54 +02:00
parent 77873f5a9d
commit 462b82a060
5 changed files with 10 additions and 30 deletions

View File

@ -68,7 +68,7 @@ func TestRebuildIndexAlwaysFull(t *testing.T) {
defer func() {
index.IndexFull = indexFull
}()
index.IndexFull = func(*index.Index, bool) bool { return true }
index.IndexFull = func(*index.Index) bool { return true }
testRebuildIndex(t, nil)
}

View File

@ -90,13 +90,12 @@ func (idx *Index) Final() bool {
}
const (
indexMaxBlobs = 50000
indexMaxBlobsCompressed = 3 * indexMaxBlobs
indexMaxAge = 10 * time.Minute
indexMaxBlobs = 50000
indexMaxAge = 10 * time.Minute
)
// IndexFull returns true iff the index is "full enough" to be saved as a preliminary index.
var IndexFull = func(idx *Index, compress bool) bool {
var IndexFull = func(idx *Index) bool {
idx.m.RLock()
defer idx.m.RUnlock()
@ -107,18 +106,12 @@ var IndexFull = func(idx *Index, compress bool) bool {
blobs += idx.byType[typ].len()
}
age := time.Since(idx.created)
var maxBlobs uint
if compress {
maxBlobs = indexMaxBlobsCompressed
} else {
maxBlobs = indexMaxBlobs
}
switch {
case age >= indexMaxAge:
debug.Log("index %p is old enough", idx, age)
return true
case blobs >= maxBlobs:
case blobs >= indexMaxBlobs:
debug.Log("index %p has %d blobs", idx, blobs)
return true
}

View File

@ -17,7 +17,6 @@ type MasterIndex struct {
idx []*Index
pendingBlobs restic.BlobSet
idxMutex sync.RWMutex
compress bool
}
// NewMasterIndex creates a new master index.
@ -33,10 +32,6 @@ func (mi *MasterIndex) clear() {
mi.idx[0].Finalize()
}
func (mi *MasterIndex) MarkCompressed() {
mi.compress = true
}
// Lookup queries all known Indexes for the ID and returns all matches.
func (mi *MasterIndex) Lookup(bh restic.BlobHandle) (pbs []restic.PackedBlob) {
mi.idxMutex.RLock()
@ -211,7 +206,7 @@ func (mi *MasterIndex) finalizeFullIndexes() []*Index {
continue
}
if IndexFull(idx, mi.compress) {
if IndexFull(idx) {
debug.Log("index %p is full", idx)
idx.Finalize()
list = append(list, idx)
@ -417,7 +412,7 @@ func (mi *MasterIndex) Rewrite(ctx context.Context, repo restic.Unpacked, exclud
newIndex := NewIndex()
for task := range rewriteCh {
// always rewrite indexes using the old format, that include a pack that must be removed or that are not full
if !task.oldFormat && len(task.idx.Packs().Intersect(excludePacks)) == 0 && IndexFull(task.idx, mi.compress) {
if !task.oldFormat && len(task.idx.Packs().Intersect(excludePacks)) == 0 && IndexFull(task.idx) {
// make sure that each pack is only stored exactly once in the index
excludePacks.Merge(task.idx.Packs())
// index is already up to date
@ -433,7 +428,7 @@ func (mi *MasterIndex) Rewrite(ctx context.Context, repo restic.Unpacked, exclud
for pbs := range task.idx.EachByPack(wgCtx, excludePacks) {
newIndex.StorePack(pbs.PackID, pbs.Blobs)
if IndexFull(newIndex, mi.compress) {
if IndexFull(newIndex) {
select {
case saveCh <- newIndex:
case <-wgCtx.Done():
@ -527,7 +522,7 @@ func (mi *MasterIndex) SaveFallback(ctx context.Context, repo restic.SaverRemove
for pbs := range idx.EachByPack(wgCtx, excludePacks) {
newIndex.StorePack(pbs.PackID, pbs.Blobs)
p.Add(1)
if IndexFull(newIndex, mi.compress) {
if IndexFull(newIndex) {
select {
case ch <- newIndex:
case <-wgCtx.Done():

View File

@ -588,19 +588,11 @@ func (r *Repository) ListPacksFromIndex(ctx context.Context, packs restic.IDSet)
// SetIndex instructs the repository to use the given index.
func (r *Repository) SetIndex(i restic.MasterIndex) error {
r.idx = i.(*index.MasterIndex)
r.configureIndex()
return r.prepareCache()
}
func (r *Repository) clearIndex() {
r.idx = index.NewMasterIndex()
r.configureIndex()
}
func (r *Repository) configureIndex() {
if r.cfg.Version >= 2 {
r.idx.MarkCompressed()
}
}
// LoadIndex loads all index files from the backend in parallel and stores them

View File

@ -376,7 +376,7 @@ func TestRepositoryIncrementalIndex(t *testing.T) {
func testRepositoryIncrementalIndex(t *testing.T, version uint) {
repo, _ := repository.TestRepositoryWithVersion(t, version)
index.IndexFull = func(*index.Index, bool) bool { return true }
index.IndexFull = func(*index.Index) bool { return true }
// add a few rounds of packs
for j := 0; j < 5; j++ {