github.com/weaviate/weaviate@v1.24.6/adapters/repos/db/lsmkv/compaction_integration_test.go (about)

     1  //                           _       _
     2  // __      _____  __ ___   ___  __ _| |_ ___
     3  // \ \ /\ / / _ \/ _` \ \ / / |/ _` | __/ _ \
     4  //  \ V  V /  __/ (_| |\ V /| | (_| | ||  __/
     5  //   \_/\_/ \___|\__,_| \_/ |_|\__,_|\__\___|
     6  //
     7  //  Copyright © 2016 - 2024 Weaviate B.V. All rights reserved.
     8  //
     9  //  CONTACT: hello@weaviate.io
    10  //
    11  
    12  //go:build integrationTest
    13  // +build integrationTest
    14  
    15  package lsmkv
    16  
    17  import (
    18  	"context"
    19  	"os"
    20  	"path/filepath"
    21  	"testing"
    22  
    23  	"github.com/sirupsen/logrus"
    24  	"github.com/sirupsen/logrus/hooks/test"
    25  	"github.com/stretchr/testify/assert"
    26  	"github.com/stretchr/testify/require"
    27  )
    28  
    29  func testCtx() context.Context {
    30  	return context.Background()
    31  }
    32  
    33  type bucketIntegrationTest struct {
    34  	name string
    35  	f    func(context.Context, *testing.T, []BucketOption)
    36  	opts []BucketOption
    37  }
    38  
    39  type bucketIntegrationTests []bucketIntegrationTest
    40  
    41  func (tests bucketIntegrationTests) run(ctx context.Context, t *testing.T) {
    42  	for _, test := range tests {
    43  		t.Run(test.name, func(t *testing.T) {
    44  			t.Run("mmap", func(t *testing.T) {
    45  				test.f(ctx, t, test.opts)
    46  			})
    47  			t.Run("pread", func(t *testing.T) {
    48  				test.f(ctx, t, append([]BucketOption{WithPread(true)}, test.opts...))
    49  			})
    50  		})
    51  	}
    52  }
    53  
    54  func TestCompaction(t *testing.T) {
    55  	ctx := testCtx()
    56  	tests := bucketIntegrationTests{
    57  		{
    58  			name: "compactionReplaceStrategy",
    59  			f: func(ctx context.Context, t *testing.T, opts []BucketOption) {
    60  				compactionReplaceStrategy(ctx, t, opts, 12116, 12116)
    61  			},
    62  			opts: []BucketOption{
    63  				WithStrategy(StrategyReplace),
    64  			},
    65  		},
    66  		{
    67  			name: "compactionReplaceStrategy_KeepTombstones",
    68  			f: func(ctx context.Context, t *testing.T, opts []BucketOption) {
    69  				compactionReplaceStrategy(ctx, t, opts, 15266, 15266)
    70  			},
    71  			opts: []BucketOption{
    72  				WithStrategy(StrategyReplace),
    73  				WithKeepTombstones(true),
    74  			},
    75  		},
    76  		{
    77  			name: "compactionReplaceStrategy_WithSecondaryKeys",
    78  			f:    compactionReplaceStrategy_WithSecondaryKeys,
    79  			opts: []BucketOption{
    80  				WithStrategy(StrategyReplace),
    81  				WithSecondaryIndices(1),
    82  			},
    83  		},
    84  		{
    85  			name: "compactionReplaceStrategy_WithSecondaryKeys_KeepTombstones",
    86  			f:    compactionReplaceStrategy_WithSecondaryKeys,
    87  			opts: []BucketOption{
    88  				WithStrategy(StrategyReplace),
    89  				WithSecondaryIndices(1),
    90  				WithKeepTombstones(true),
    91  			},
    92  		},
    93  		{
    94  			name: "compactionReplaceStrategy_RemoveUnnecessaryDeletes",
    95  			f:    compactionReplaceStrategy_RemoveUnnecessaryDeletes,
    96  			opts: []BucketOption{
    97  				WithStrategy(StrategyReplace),
    98  			},
    99  		},
   100  		{
   101  			name: "compactionReplaceStrategy_RemoveUnnecessaryDeletes_KeepTombstones",
   102  			f:    compactionReplaceStrategy_RemoveUnnecessaryDeletes,
   103  			opts: []BucketOption{
   104  				WithStrategy(StrategyReplace),
   105  				WithKeepTombstones(true),
   106  			},
   107  		},
   108  		{
   109  			name: "compactionReplaceStrategy_RemoveUnnecessaryUpdates",
   110  			f:    compactionReplaceStrategy_RemoveUnnecessaryUpdates,
   111  			opts: []BucketOption{
   112  				WithStrategy(StrategyReplace),
   113  			},
   114  		},
   115  		{
   116  			name: "compactionReplaceStrategy_RemoveUnnecessaryUpdates_KeepTombstones",
   117  			f:    compactionReplaceStrategy_RemoveUnnecessaryUpdates,
   118  			opts: []BucketOption{
   119  				WithStrategy(StrategyReplace),
   120  				WithKeepTombstones(true),
   121  			},
   122  		},
   123  		{
   124  			name: "compactionReplaceStrategy_FrequentPutDeleteOperations",
   125  			f:    compactionReplaceStrategy_FrequentPutDeleteOperations,
   126  			opts: []BucketOption{
   127  				WithStrategy(StrategyReplace),
   128  			},
   129  		},
   130  		{
   131  			name: "compactionReplaceStrategy_FrequentPutDeleteOperations_KeepTombstones",
   132  			f:    compactionReplaceStrategy_FrequentPutDeleteOperations,
   133  			opts: []BucketOption{
   134  				WithStrategy(StrategyReplace),
   135  				WithKeepTombstones(true),
   136  			},
   137  		},
   138  		{
   139  			name: "compactionReplaceStrategy_FrequentPutDeleteOperations_WithSecondaryKeys",
   140  			f:    compactionReplaceStrategy_FrequentPutDeleteOperations_WithSecondaryKeys,
   141  			opts: []BucketOption{
   142  				WithStrategy(StrategyReplace),
   143  				WithSecondaryIndices(1),
   144  			},
   145  		},
   146  		{
   147  			name: "compactionReplaceStrategy_FrequentPutDeleteOperations_WithSecondaryKeys_KeepTombstones",
   148  			f:    compactionReplaceStrategy_FrequentPutDeleteOperations_WithSecondaryKeys,
   149  			opts: []BucketOption{
   150  				WithStrategy(StrategyReplace),
   151  				WithSecondaryIndices(1),
   152  				WithKeepTombstones(true),
   153  			},
   154  		},
   155  
   156  		{
   157  			name: "compactionSetStrategy",
   158  			f: func(ctx context.Context, t *testing.T, opts []BucketOption) {
   159  				compactionSetStrategy(ctx, t, opts, 6836, 6836)
   160  			},
   161  			opts: []BucketOption{
   162  				WithStrategy(StrategySetCollection),
   163  			},
   164  		},
   165  		{
   166  			name: "compactionSetStrategy_KeepTombstones",
   167  			f: func(ctx context.Context, t *testing.T, opts []BucketOption) {
   168  				compactionSetStrategy(ctx, t, opts, 9756, 9756)
   169  			},
   170  			opts: []BucketOption{
   171  				WithStrategy(StrategySetCollection),
   172  				WithKeepTombstones(true),
   173  			},
   174  		},
   175  		{
   176  			name: "compactionSetStrategy_RemoveUnnecessary",
   177  			f:    compactionSetStrategy_RemoveUnnecessary,
   178  			opts: []BucketOption{
   179  				WithStrategy(StrategySetCollection),
   180  			},
   181  		},
   182  		{
   183  			name: "compactionSetStrategy_RemoveUnnecessary_KeepTombstones",
   184  			f:    compactionSetStrategy_RemoveUnnecessary,
   185  			opts: []BucketOption{
   186  				WithStrategy(StrategySetCollection),
   187  				WithKeepTombstones(true),
   188  			},
   189  		},
   190  		{
   191  			name: "compactionSetStrategy_FrequentPutDeleteOperations",
   192  			f:    compactionSetStrategy_FrequentPutDeleteOperations,
   193  			opts: []BucketOption{
   194  				WithStrategy(StrategySetCollection),
   195  			},
   196  		},
   197  		{
   198  			name: "compactionSetStrategy_FrequentPutDeleteOperations_KeepTombstones",
   199  			f:    compactionSetStrategy_FrequentPutDeleteOperations,
   200  			opts: []BucketOption{
   201  				WithStrategy(StrategySetCollection),
   202  				WithKeepTombstones(true),
   203  			},
   204  		},
   205  
   206  		{
   207  			name: "compactionMapStrategy",
   208  			f: func(ctx context.Context, t *testing.T, opts []BucketOption) {
   209  				compactionMapStrategy(ctx, t, opts, 10676, 10676)
   210  			},
   211  			opts: []BucketOption{
   212  				WithStrategy(StrategyMapCollection),
   213  			},
   214  		},
   215  		{
   216  			name: "compactionMapStrategy_KeepTombstones",
   217  			f: func(ctx context.Context, t *testing.T, opts []BucketOption) {
   218  				compactionMapStrategy(ctx, t, opts, 13416, 13416)
   219  			},
   220  			opts: []BucketOption{
   221  				WithStrategy(StrategyMapCollection),
   222  				WithKeepTombstones(true),
   223  			},
   224  		},
   225  		{
   226  			name: "compactionMapStrategy_RemoveUnnecessary",
   227  			f:    compactionMapStrategy_RemoveUnnecessary,
   228  			opts: []BucketOption{
   229  				WithStrategy(StrategyMapCollection),
   230  			},
   231  		},
   232  		{
   233  			name: "compactionMapStrategy_RemoveUnnecessary_KeepTombstones",
   234  			f:    compactionMapStrategy_RemoveUnnecessary,
   235  			opts: []BucketOption{
   236  				WithStrategy(StrategyMapCollection),
   237  				WithKeepTombstones(true),
   238  			},
   239  		},
   240  		{
   241  			name: "compactionMapStrategy_FrequentPutDeleteOperations",
   242  			f:    compactionMapStrategy_FrequentPutDeleteOperations,
   243  			opts: []BucketOption{
   244  				WithStrategy(StrategyMapCollection),
   245  			},
   246  		},
   247  		{
   248  			name: "compactionMapStrategy_FrequentPutDeleteOperations_KeepTombstones",
   249  			f:    compactionMapStrategy_FrequentPutDeleteOperations,
   250  			opts: []BucketOption{
   251  				WithStrategy(StrategyMapCollection),
   252  				WithKeepTombstones(true),
   253  			},
   254  		},
   255  
   256  		{
   257  			name: "compactionRoaringSetStrategy_Random",
   258  			f:    compactionRoaringSetStrategy_Random,
   259  			opts: []BucketOption{
   260  				WithStrategy(StrategyRoaringSet),
   261  			},
   262  		},
   263  		{
   264  			name: "compactionRoaringSetStrategy_Random_KeepTombstones",
   265  			f:    compactionRoaringSetStrategy_Random,
   266  			opts: []BucketOption{
   267  				WithStrategy(StrategyRoaringSet),
   268  				WithKeepTombstones(true),
   269  			},
   270  		},
   271  		{
   272  			name: "compactionRoaringSetStrategy",
   273  			f: func(ctx context.Context, t *testing.T, opts []BucketOption) {
   274  				compactionRoaringSetStrategy(ctx, t, opts, 19168, 19168)
   275  			},
   276  			opts: []BucketOption{
   277  				WithStrategy(StrategyRoaringSet),
   278  			},
   279  		},
   280  		{
   281  			name: "compactionRoaringSetStrategy_KeepTombstones",
   282  			f: func(ctx context.Context, t *testing.T, opts []BucketOption) {
   283  				compactionRoaringSetStrategy(ctx, t, opts, 29792, 29792)
   284  			},
   285  			opts: []BucketOption{
   286  				WithStrategy(StrategyRoaringSet),
   287  				WithKeepTombstones(true),
   288  			},
   289  		},
   290  		{
   291  			name: "compactionRoaringSetStrategy_RemoveUnnecessary",
   292  			f:    compactionRoaringSetStrategy_RemoveUnnecessary,
   293  			opts: []BucketOption{
   294  				WithStrategy(StrategyRoaringSet),
   295  			},
   296  		},
   297  		{
   298  			name: "compactionRoaringSetStrategy_RemoveUnnecessary_KeepTombstones",
   299  			f:    compactionRoaringSetStrategy_RemoveUnnecessary,
   300  			opts: []BucketOption{
   301  				WithStrategy(StrategyRoaringSet),
   302  				WithKeepTombstones(true),
   303  			},
   304  		},
   305  		{
   306  			name: "compactionRoaringSetStrategy_FrequentPutDeleteOperations",
   307  			f:    compactionRoaringSetStrategy_FrequentPutDeleteOperations,
   308  			opts: []BucketOption{
   309  				WithStrategy(StrategyRoaringSet),
   310  			},
   311  		},
   312  		{
   313  			name: "compactionRoaringSetStrategy_FrequentPutDeleteOperations_KeepTombstones",
   314  			f:    compactionRoaringSetStrategy_FrequentPutDeleteOperations,
   315  			opts: []BucketOption{
   316  				WithStrategy(StrategyRoaringSet),
   317  				WithKeepTombstones(true),
   318  			},
   319  		},
   320  	}
   321  	tests.run(ctx, t)
   322  }
   323  
   324  func nullLogger() logrus.FieldLogger {
   325  	log, _ := test.NewNullLogger()
   326  	return log
   327  }
   328  
   329  func copyByteSlice(src []byte) []byte {
   330  	dst := make([]byte, len(src))
   331  	copy(dst, src)
   332  	return dst
   333  }
   334  
   335  func assertSingleSegmentOfSize(t *testing.T, bucket *Bucket, expectedMinSize, expectedMaxSize int64) {
   336  	files, err := bucket.ListFiles(context.Background(), bucket.dir)
   337  	require.NoError(t, err)
   338  
   339  	dbFiles := make([]string, 0, len(files))
   340  	for _, f := range files {
   341  		if filepath.Ext(f) == ".db" {
   342  			dbFiles = append(dbFiles, f)
   343  		}
   344  	}
   345  	require.Len(t, dbFiles, 1)
   346  
   347  	fi, err := os.Stat(dbFiles[0])
   348  	require.NoError(t, err)
   349  	assert.LessOrEqual(t, expectedMinSize, fi.Size())
   350  	assert.GreaterOrEqual(t, expectedMaxSize, fi.Size())
   351  }
   352  
   353  func assertSecondSegmentOfSize(t *testing.T, bucket *Bucket, expectedMinSize, expectedMaxSize int64) {
   354  	files, err := bucket.ListFiles(context.Background(), bucket.dir)
   355  	require.NoError(t, err)
   356  
   357  	dbFiles := make([]string, 0, len(files))
   358  	for _, f := range files {
   359  		if filepath.Ext(f) == ".db" {
   360  			dbFiles = append(dbFiles, f)
   361  		}
   362  	}
   363  	require.Len(t, dbFiles, 2)
   364  
   365  	fi, err := os.Stat(dbFiles[1])
   366  	require.NoError(t, err)
   367  	assert.LessOrEqual(t, expectedMinSize, fi.Size())
   368  	assert.GreaterOrEqual(t, expectedMaxSize, fi.Size())
   369  }