github.com/safing/portbase@v0.19.5/database/interface_cache_test.go (about)

     1  package database
     2  
     3  import (
     4  	"context"
     5  	"fmt"
     6  	"strconv"
     7  	"sync"
     8  	"testing"
     9  )
    10  
    11  func benchmarkCacheWriting(b *testing.B, storageType string, cacheSize int, sampleSize int, delayWrites bool) { //nolint:gocognit,gocyclo,thelper
    12  	b.Run(fmt.Sprintf("CacheWriting_%s_%d_%d_%v", storageType, cacheSize, sampleSize, delayWrites), func(b *testing.B) {
    13  		// Setup Benchmark.
    14  
    15  		// Create database.
    16  		dbName := fmt.Sprintf("cache-w-benchmark-%s-%d-%d-%v", storageType, cacheSize, sampleSize, delayWrites)
    17  		_, err := Register(&Database{
    18  			Name:        dbName,
    19  			Description: fmt.Sprintf("Cache Benchmark Database for %s", storageType),
    20  			StorageType: storageType,
    21  		})
    22  		if err != nil {
    23  			b.Fatal(err)
    24  		}
    25  
    26  		// Create benchmark interface.
    27  		options := &Options{
    28  			Local:     true,
    29  			Internal:  true,
    30  			CacheSize: cacheSize,
    31  		}
    32  		if cacheSize > 0 && delayWrites {
    33  			options.DelayCachedWrites = dbName
    34  		}
    35  		db := NewInterface(options)
    36  
    37  		// Start
    38  		ctx, cancelCtx := context.WithCancel(context.Background())
    39  		var wg sync.WaitGroup
    40  		if cacheSize > 0 && delayWrites {
    41  			wg.Add(1)
    42  			go func() {
    43  				err := db.DelayedCacheWriter(ctx)
    44  				if err != nil {
    45  					panic(err)
    46  				}
    47  				wg.Done()
    48  			}()
    49  		}
    50  
    51  		// Start Benchmark.
    52  		b.ResetTimer()
    53  		for i := 0; i < b.N; i++ {
    54  			testRecordID := i % sampleSize
    55  			r := NewExample(
    56  				dbName+":"+strconv.Itoa(testRecordID),
    57  				"A",
    58  				1,
    59  			)
    60  			err = db.Put(r)
    61  			if err != nil {
    62  				b.Fatal(err)
    63  			}
    64  		}
    65  
    66  		// End cache writer and wait
    67  		cancelCtx()
    68  		wg.Wait()
    69  	})
    70  }
    71  
    72  func benchmarkCacheReadWrite(b *testing.B, storageType string, cacheSize int, sampleSize int, delayWrites bool) { //nolint:gocognit,gocyclo,thelper
    73  	b.Run(fmt.Sprintf("CacheReadWrite_%s_%d_%d_%v", storageType, cacheSize, sampleSize, delayWrites), func(b *testing.B) {
    74  		// Setup Benchmark.
    75  
    76  		// Create database.
    77  		dbName := fmt.Sprintf("cache-rw-benchmark-%s-%d-%d-%v", storageType, cacheSize, sampleSize, delayWrites)
    78  		_, err := Register(&Database{
    79  			Name:        dbName,
    80  			Description: fmt.Sprintf("Cache Benchmark Database for %s", storageType),
    81  			StorageType: storageType,
    82  		})
    83  		if err != nil {
    84  			b.Fatal(err)
    85  		}
    86  
    87  		// Create benchmark interface.
    88  		options := &Options{
    89  			Local:     true,
    90  			Internal:  true,
    91  			CacheSize: cacheSize,
    92  		}
    93  		if cacheSize > 0 && delayWrites {
    94  			options.DelayCachedWrites = dbName
    95  		}
    96  		db := NewInterface(options)
    97  
    98  		// Start
    99  		ctx, cancelCtx := context.WithCancel(context.Background())
   100  		var wg sync.WaitGroup
   101  		if cacheSize > 0 && delayWrites {
   102  			wg.Add(1)
   103  			go func() {
   104  				err := db.DelayedCacheWriter(ctx)
   105  				if err != nil {
   106  					panic(err)
   107  				}
   108  				wg.Done()
   109  			}()
   110  		}
   111  
   112  		// Start Benchmark.
   113  		b.ResetTimer()
   114  		writing := true
   115  		for i := 0; i < b.N; i++ {
   116  			testRecordID := i % sampleSize
   117  			key := dbName + ":" + strconv.Itoa(testRecordID)
   118  
   119  			if i > 0 && testRecordID == 0 {
   120  				writing = !writing // switch between reading and writing every samplesize
   121  			}
   122  
   123  			if writing {
   124  				r := NewExample(key, "A", 1)
   125  				err = db.Put(r)
   126  			} else {
   127  				_, err = db.Get(key)
   128  			}
   129  			if err != nil {
   130  				b.Fatal(err)
   131  			}
   132  		}
   133  
   134  		// End cache writer and wait
   135  		cancelCtx()
   136  		wg.Wait()
   137  	})
   138  }
   139  
   140  func BenchmarkCache(b *testing.B) {
   141  	for _, storageType := range []string{"bbolt", "hashmap"} {
   142  		benchmarkCacheWriting(b, storageType, 32, 8, false)
   143  		benchmarkCacheWriting(b, storageType, 32, 8, true)
   144  		benchmarkCacheWriting(b, storageType, 32, 1024, false)
   145  		benchmarkCacheWriting(b, storageType, 32, 1024, true)
   146  		benchmarkCacheWriting(b, storageType, 512, 1024, false)
   147  		benchmarkCacheWriting(b, storageType, 512, 1024, true)
   148  
   149  		benchmarkCacheReadWrite(b, storageType, 32, 8, false)
   150  		benchmarkCacheReadWrite(b, storageType, 32, 8, true)
   151  		benchmarkCacheReadWrite(b, storageType, 32, 1024, false)
   152  		benchmarkCacheReadWrite(b, storageType, 32, 1024, true)
   153  		benchmarkCacheReadWrite(b, storageType, 512, 1024, false)
   154  		benchmarkCacheReadWrite(b, storageType, 512, 1024, true)
   155  	}
   156  }