Clarify "Memory usage" section in readme

Moved from GitHub badger/1304

Posted by luca-moser:

The readme has a small section about how to tweak BadgerDB to consume less memory. However, the section doesn’t really describe any of the parameters in depth or allow the reader to be able to make an educated guess on how much memory his/her BadgerDB instance will consume.

The reason I’m bringing this up is that we’re heavily using BadgerDB in our software but the options around it feel like a blackbox where one has to basically change parameters without a clear sight.

Is it possible to extend that section with actual explanations how the given options change Badger’s memory consumption? It would be good if users of BadgerDB are able given the options and their knowledge about the kind of data they store, to derive the memory consumption they will face.

jarifibrahim commented :

Thank you for raising the issue @luca-moser. Updating the documentation is on our list of to-do things and we’ll try to get it updated.

Meanwhile, if you need help with reducing memory usage, I’ll be happy to help. Please do share your badger options so that I can suggest some changes.

alexsporn commented :

Hi @jarifibrahim, Luca told me to post our findings here so you can take a look.

Our database folder is about 300GB big. Just opening the database consumes 13GB ram with the settings we are using.

I ran the following “minimal badger” using our settings that just opens the database and runs the garbage collector every 5 minutes.

package main


import (
	"fmt"
	"os"
	"os/signal"
	"runtime"
	"sync"
	"syscall"
	"time"

	"github.com/dgraph-io/badger/v2"
	"github.com/dgraph-io/badger/v2/options"
)

var (
	deathWaitGroup         = &sync.WaitGroup{}
	memUpdateTicker           *time.Ticker
	cleanupTicker           *time.Ticker
	tickerQuitSignal chan struct{}

	instance  *badger.DB
	once      sync.Once
	directory = "mainnetdb"
)

func main() {
	deathWaitGroup.Add(1)
	printMemoryStats()
	db := getBadgerInstance()
	printMemoryStats()

	memUpdateTicker = time.NewTicker(1 * time.Minute)
	cleanupTicker = time.NewTicker(5 * time.Minute)
	tickerQuitSignal = make(chan struct{})
	go func() {
		for {
			select {
			case <-tickerQuitSignal:
				return
			case <-memUpdateTicker.C:
				printMemoryStats()
			case <- cleanupTicker.C:
				cleanupBadgerInstance()
			}
		}
	}()

	go gracefullyDies()
	deathWaitGroup.Wait()

	fmt.Println(time.Now(),
		"[Badger]",
		"Closing badger")
	db.Close()
	printMemoryStats()
	fmt.Println(time.Now(),
		"Bye!")
}

func printMemoryStats() {
	var m runtime.MemStats
	runtime.ReadMemStats(&m)

	fmt.Println(time.Now(),
		"[Memory]",
		"Sys:", m.Sys, ",",
		"HeapAlloc:", m.HeapAlloc, ",",
		"HeapSys:", m.HeapSys, ",",
		"HeapInuse:", m.HeapInuse, ",",
		"HeapIdle:", m.HeapIdle, ",",
		"HeapReleased:", m.HeapReleased, ",",
		"HeapObjects:", m.HeapObjects, ",",
		"MSpanInuse:", m.MSpanInuse, ",",
		"MCacheInuse:", m.MCacheInuse, ",",
		"StackSys:", m.StackSys, ",",
		"NumGC:", m.NumGC, ",",
		"LastPauseGC:", m.PauseNs[(m.NumGC+255)%256],
		)
}

func gracefullyDies() {
	ch := make(chan os.Signal, 1)
	signal.Notify(ch, os.Interrupt, syscall.SIGTERM, syscall.SIGINT)

	sig := <-ch // waits for death signal

	fmt.Println(time.Now(),
		"Caught signal '", sig,  "': shutting down. Please wait...")

	deathWaitGroup.Done()
}

func exists(path string) (bool, error) {
	_, err := os.Stat(path)
	if err == nil {
		return true, nil
	}
	if os.IsNotExist(err) {
		return false, nil
	}
	return false, err
}

func checkDir(dir string) error {
	exists, err := exists(dir)
	if err != nil {
		return err
	}

	if !exists {
		return os.Mkdir(dir, 0700)
	}
	return nil
}

func getBadgerInstance() *badger.DB {
	once.Do(func() {

		fmt.Println(time.Now(),
			"[Badger]",
			"Initialize badger at", directory)

		if err := checkDir(directory); err != nil {
			panic(err)
		}

		var opts badger.Options

		opts = badger.DefaultOptions(directory)
		opts.Logger = nil

		opts.LevelSizeMultiplier = 10
		opts.TableLoadingMode = options.MemoryMap
		opts.ValueLogLoadingMode = options.FileIO
		opts.MaxLevels = 7
		opts.MaxTableSize = 67108864
		opts.NumCompactors = 1
		opts.NumLevelZeroTables = 1
		opts.NumLevelZeroTablesStall = 2
		opts.NumMemtables = 1
		opts.BloomFalsePositive = 0.01
		opts.BlockSize = 4 * 1024
		opts.SyncWrites = false
		opts.NumVersionsToKeep = 1
		opts.CompactL0OnClose = false
		opts.KeepL0InMemory = false
		opts.VerifyValueChecksum = false
		opts.MaxCacheSize = 200000000
		opts.ZSTDCompressionLevel = 1
		opts.Compression = options.None
		opts.ValueLogFileSize = 1073741823
		opts.ValueLogMaxEntries = 33554431
		opts.ValueThreshold = 32
		opts.Truncate = false
		opts.LogRotatesToFlush = 2
		opts.EventLogging = false

		if runtime.GOOS == "windows" {
			opts = opts.WithTruncate(true)
		}

		db, err := badger.Open(opts)
		if err != nil {
			panic(err)
		}
		instance = db
	})
	return instance
}

func cleanupBadgerInstance() {

	db := getBadgerInstance()

	fmt.Println(time.Now(),
		"[Badger]",
		"Run garbage collection")

	var err error
	for err == nil {
		err = db.RunValueLogGC(0.7)
	}
}

Running on go 1.14.2 and badger 2.0.3 the output of this script is:

m=+0.000874372 [Memory] Sys: 71125000 , HeapAlloc: 206336 , HeapSys: 66813952 , HeapInuse: 663552 , HeapIdle: 66150400 , HeapReleased: 66150400 , HeapObjects: 929 , MSpanInuse: 19448 , MCacheInuse: 3472 , StackSys: 294912 , NumGC: 0 , LastPauseGC: 0
m=+0.000947733 [Badger] Initialize badger at mainnetdb
m=+23.169028430 [Memory] Sys: 13198831080 , HeapAlloc: 9874474104 , HeapSys: 12615483392 , HeapInuse: 9885589504 , HeapIdle: 2729893888 , HeapReleased: 25706496 , HeapObjects: 72432308 , MSpanInuse: 95966496 , MCacheInuse: 3472 , StackSys: 425984 , NumGC: 18 , LastPauseGC: 70260
m=+83.169241833 [Memory] Sys: 13618802200 , HeapAlloc: 8512172064 , HeapSys: 13018562560 , HeapInuse: 8519155712 , HeapIdle: 4499406848 , HeapReleased: 138412032 , HeapObjects: 63042716 , MSpanInuse: 82406072 , MCacheInuse: 3472 , StackSys: 557056 , NumGC: 18 , LastPauseGC: 70260
m=+144.188312677 [Memory] Sys: 13618802200 , HeapAlloc: 8512718048 , HeapSys: 13018071040 , HeapInuse: 8519622656 , HeapIdle: 4498448384 , HeapReleased: 138420224 , HeapObjects: 63050393 , MSpanInuse: 82414776 , MCacheInuse: 3472 , StackSys: 557056 , NumGC: 19 , LastPauseGC: 20030
m=+203.169118149 [Memory] Sys: 13618802200 , HeapAlloc: 7705851968 , HeapSys: 13018562560 , HeapInuse: 7724294144 , HeapIdle: 5294268416 , HeapReleased: 2229215232 , HeapObjects: 60794170 , MSpanInuse: 80215248 , MCacheInuse: 3472 , StackSys: 557056 , NumGC: 19 , LastPauseGC: 20030
m=+263.169157010 [Memory] Sys: 13618802200 , HeapAlloc: 7706582088 , HeapSys: 13018562560 , HeapInuse: 7724949504 , HeapIdle: 5293613056 , HeapReleased: 3845365760 , HeapObjects: 60802920 , MSpanInuse: 80223952 , MCacheInuse: 3472 , StackSys: 557056 , NumGC: 19 , LastPauseGC: 20030
m=+323.169177991 [Memory] Sys: 13618802200 , HeapAlloc: 7698655968 , HeapSys: 13018595328 , HeapInuse: 7717044224 , HeapIdle: 5301551104 , HeapReleased: 4529086464 , HeapObjects: 60794138 , MSpanInuse: 80213752 , MCacheInuse: 3472 , StackSys: 524288 , NumGC: 20 , LastPauseGC: 79151
m=+323.169231412 [Badger] Run garbage collection
m=+383.169237654 [Memory] Sys: 13619326488 , HeapAlloc: 8675305976 , HeapSys: 13018595328 , HeapInuse: 8695496704 , HeapIdle: 4323098624 , HeapReleased: 4323065856 , HeapObjects: 74470390 , MSpanInuse: 95846136 , MCacheInuse: 3472 , StackSys: 524288 , NumGC: 20 , LastPauseGC: 79151
m=+443.169400672 [Memory] Sys: 13619326488 , HeapAlloc: 7698664384 , HeapSys: 13018595328 , HeapInuse: 7717175296 , HeapIdle: 5301420032 , HeapReleased: 4322516992 , HeapObjects: 60794227 , MSpanInuse: 80199744 , MCacheInuse: 3472 , StackSys: 524288 , NumGC: 21 , LastPauseGC: 54881
m=+503.169174065 [Memory] Sys: 13619326488 , HeapAlloc: 7699394768 , HeapSys: 13018595328 , HeapInuse: 7717830656 , HeapIdle: 5300764672 , HeapReleased: 4322516992 , HeapObjects: 60802979 , MSpanInuse: 80208448 , MCacheInuse: 3472 , StackSys: 524288 , NumGC: 21 , LastPauseGC: 54881
m=+563.169219106 [Memory] Sys: 13619326488 , HeapAlloc: 7698663000 , HeapSys: 13018595328 , HeapInuse: 7717134336 , HeapIdle: 5301460992 , HeapReleased: 4528979968 , HeapObjects: 60794222 , MSpanInuse: 80209128 , MCacheInuse: 3472 , StackSys: 524288 , NumGC: 22 , LastPauseGC: 39411
m=+623.169170748 [Memory] Sys: 13619326488 , HeapAlloc: 7699393384 , HeapSys: 13018595328 , HeapInuse: 7717789696 , HeapIdle: 5300805632 , HeapReleased: 4528906240 , HeapObjects: 60802974 , MSpanInuse: 80209128 , MCacheInuse: 3472 , StackSys: 524288 , NumGC: 22 , LastPauseGC: 39411
m=+623.169202649 [Badger] Run garbage collection
m=+683.169518460 [Memory] Sys: 13619850776 , HeapAlloc: 8651915792 , HeapSys: 13018595328 , HeapInuse: 8670076928 , HeapIdle: 4348518400 , HeapReleased: 3934584832 , HeapObjects: 75124542 , MSpanInuse: 95608816 , MCacheInuse: 3472 , StackSys: 524288 , NumGC: 23 , LastPauseGC: 587954
m=+743.169230752 [Memory] Sys: 13619850776 , HeapAlloc: 8652647352 , HeapSys: 13018595328 , HeapInuse: 8670765056 , HeapIdle: 4347830272 , HeapReleased: 3934584832 , HeapObjects: 75133299 , MSpanInuse: 95626224 , MCacheInuse: 3472 , StackSys: 524288 , NumGC: 23 , LastPauseGC: 587954
m=+803.169181087 [Memory] Sys: 13619850776 , HeapAlloc: 7698667280 , HeapSys: 13018595328 , HeapInuse: 7717257216 , HeapIdle: 5301338112 , HeapReleased: 3934584832 , HeapObjects: 60794270 , MSpanInuse: 80205184 , MCacheInuse: 3472 , StackSys: 524288 , NumGC: 24 , LastPauseGC: 183622
m=+863.169221220 [Memory] Sys: 13619850776 , HeapAlloc: 7699397664 , HeapSys: 13018595328 , HeapInuse: 7717912576 , HeapIdle: 5300682752 , HeapReleased: 3934584832 , HeapObjects: 60803022 , MSpanInuse: 80205184 , MCacheInuse: 3472 , StackSys: 524288 , NumGC: 24 , LastPauseGC: 183622
m=+923.169166031 [Memory] Sys: 13619850776 , HeapAlloc: 7698666440 , HeapSys: 13018595328 , HeapInuse: 7717208064 , HeapIdle: 5301387264 , HeapReleased: 4528889856 , HeapObjects: 60794265 , MSpanInuse: 80212392 , MCacheInuse: 3472 , StackSys: 524288 , NumGC: 25 , LastPauseGC: 18920
m=+923.169234972 [Badger] Run garbage collection
m=+983.169253567 [Memory] Sys: 13621685784 , HeapAlloc: 9319352112 , HeapSys: 13018595328 , HeapInuse: 9341632512 , HeapIdle: 3676962816 , HeapReleased: 3676930048 , HeapObjects: 84584548 , MSpanInuse: 106942376 , MCacheInuse: 3472 , StackSys: 524288 , NumGC: 25 , LastPauseGC: 18920
m=+1043.169279604 [Memory] Sys: 13621685784 , HeapAlloc: 7698670656 , HeapSys: 13018595328 , HeapInuse: 7717314560 , HeapIdle: 5301280768 , HeapReleased: 3676356608 , HeapObjects: 60794309 , MSpanInuse: 80214024 , MCacheInuse: 3472 , StackSys: 524288 , NumGC: 26 , LastPauseGC: 9370
m=+1103.169239449 [Memory] Sys: 13621685784 , HeapAlloc: 7699401056 , HeapSys: 13018595328 , HeapInuse: 7717961728 , HeapIdle: 5300633600 , HeapReleased: 3676348416 , HeapObjects: 60803062 , MSpanInuse: 80214024 , MCacheInuse: 3472 , StackSys: 524288 , NumGC: 26 , LastPauseGC: 9370
m=+1163.169194404 [Memory] Sys: 13621685784 , HeapAlloc: 7698669272 , HeapSys: 13018595328 , HeapInuse: 7717273600 , HeapIdle: 5301321728 , HeapReleased: 4528840704 , HeapObjects: 60794304 , MSpanInuse: 80207224 , MCacheInuse: 3472 , StackSys: 524288 , NumGC: 27 , LastPauseGC: 38011
m=+1199.907555672 Caught signal ' interrupt ': shutting down. Please wait...
m=+1199.908137688 [Badger] Closing badger
m=+1200.259970905 [Memory] Sys: 13621685784 , HeapAlloc: 7771776192 , HeapSys: 13018595328 , HeapInuse: 7790370816 , HeapIdle: 5228224512 , HeapReleased: 4456488960 , HeapObjects: 60803175 , MSpanInuse: 80215928 , MCacheInuse: 3472 , StackSys: 524288 , NumGC: 27 , LastPauseGC: 38011
m=+1200.260005255 Bye!

The database is made out of:
282 vlog files
1896 sst files

Is there any way to reduce the base memory consumption or is this normal for a database this size?

Thanks in advance for any tips

alexsporn commented :

This is another run of the same “minimal_badger” code on the same database after our app crashed due to an OOM error. Here you can see that the same code is consuming more and more ram although no one is using the database actively.

m=+0.000845896 [Memory] Sys: 71387144 , HeapAlloc: 208096 , HeapSys: 66781184 , HeapInuse: 573440 , HeapIdle: 66207744 , HeapReleased: 66207744 , HeapObjects: 933 , MSpanInuse: 19448 , MCacheInuse: 3472 , StackSys: 327680 , NumGC: 0 , LastPauseGC: 0
m=+0.000914236 [Badger] Initialize badger at mainnetdb
m=+28.707498249 [Memory] Sys: 13691745824 , HeapAlloc: 8722318896 , HeapSys: 13085835264 , HeapInuse: 8736260096 , HeapIdle: 4349575168 , HeapReleased: 13582336 , HeapObjects: 67055770 , MSpanInuse: 87043672 , MCacheInuse: 3472 , StackSys: 393216 , NumGC: 18 , LastPauseGC: 50210
m=+88.720437207 [Memory] Sys: 16465708896 , HeapAlloc: 13410817592 , HeapSys: 15769763840 , HeapInuse: 13418045440 , HeapIdle: 2351718400 , HeapReleased: 34209792 , HeapObjects: 76577608 , MSpanInuse: 94703192 , MCacheInuse: 3472 , StackSys: 819200 , NumGC: 18 , LastPauseGC: 50210
m=+148.714798156 [Memory] Sys: 19585781960 , HeapAlloc: 15413066784 , HeapSys: 18789564416 , HeapInuse: 15424413696 , HeapIdle: 3365150720 , HeapReleased: 28344320 , HeapObjects: 71381338 , MSpanInuse: 89233408 , MCacheInuse: 3472 , StackSys: 917504 , NumGC: 19 , LastPauseGC: 18880
m=+208.710883963 [Memory] Sys: 24023102152 , HeapAlloc: 22531947560 , HeapSys: 23083843584 , HeapInuse: 22543712256 , HeapIdle: 540131328 , HeapReleased: 56868864 , HeapObjects: 85729151 , MSpanInuse: 100583424 , MCacheInuse: 3472 , StackSys: 1605632 , NumGC: 19 , LastPauseGC: 18880
m=+268.707607149 [Memory] Sys: 27071280168 , HeapAlloc: 23873971216 , HeapSys: 26036699136 , HeapInuse: 23885365248 , HeapIdle: 2151333888 , HeapReleased: 117227520 , HeapObjects: 78942968 , MSpanInuse: 97185600 , MCacheInuse: 3472 , StackSys: 1540096 , NumGC: 20 , LastPauseGC: 305711
m=+328.709350230 [Memory] Sys: 30812583384 , HeapAlloc: 29367080984 , HeapSys: 29660217344 , HeapInuse: 29379067904 , HeapIdle: 281149440 , HeapReleased: 81174528 , HeapObjects: 89703588 , MSpanInuse: 105854784 , MCacheInuse: 3472 , StackSys: 1900544 , NumGC: 20 , LastPauseGC: 305711
m=+328.709380511 [Badger] Run garbage collection
m=+388.717753646 [Memory] Sys: 34503622528 , HeapAlloc: 30352122272 , HeapSys: 33217085440 , HeapInuse: 30362099712 , HeapIdle: 2854985728 , HeapReleased: 20447232 , HeapObjects: 90511999 , MSpanInuse: 110724264 , MCacheInuse: 3472 , StackSys: 1802240 , NumGC: 21 , LastPauseGC: 5685610
m=+448.718654834 [Memory] Sys: 37972951312 , HeapAlloc: 36360303704 , HeapSys: 36572102656 , HeapInuse: 36371333120 , HeapIdle: 200769536 , HeapReleased: 120061952 , HeapObjects: 102171925 , MSpanInuse: 122657448 , MCacheInuse: 3472 , StackSys: 2228224 , NumGC: 21 , LastPauseGC: 5685610
m=+508.707590058 [Memory] Sys: 41579049648 , HeapAlloc: 36900402216 , HeapSys: 40061829120 , HeapInuse: 36973035520 , HeapIdle: 3088793600 , HeapReleased: 148324352 , HeapObjects: 88156957 , MSpanInuse: 111446968 , MCacheInuse: 3472 , StackSys: 2162688 , NumGC: 22 , LastPauseGC: 47260
m=+568.714304882 [Memory] Sys: 44769117216 , HeapAlloc: 42315699792 , HeapSys: 43148443648 , HeapInuse: 42389217280 , HeapIdle: 759226368 , HeapReleased: 196558848 , HeapObjects: 99265608 , MSpanInuse: 122901432 , MCacheInuse: 3472 , StackSys: 2555904 , NumGC: 22 , LastPauseGC: 47260
m=+610.452161695 Caught signal ' interrupt ': shutting down. Please wait...
m=+610.486983321 [Badger] Closing badger
m=+628.707812895 [Memory] Sys: 48094778784 , HeapAlloc: 44581802344 , HeapSys: 46369669120 , HeapInuse: 44653928448 , HeapIdle: 1715740672 , HeapReleased: 141246464 , HeapObjects: 94767407 , MSpanInuse: 120641928 , MCacheInuse: 3472 , StackSys: 2555904 , NumGC: 23 , LastPauseGC: 8033315
m=+628.707853895 [Badger] Run garbage collection
m=+688.793998345 [Memory] Sys: 51565283120 , HeapAlloc: 49591031736 , HeapSys: 49724784640 , HeapInuse: 49664180224 , HeapIdle: 60604416 , HeapReleased: 60538880 , HeapObjects: 105113881 , MSpanInuse: 131391368 , MCacheInuse: 3472 , StackSys: 2883584 , NumGC: 23 , LastPauseGC: 8033315
m=+730.413494524 [Memory] Sys: 53718409256 , HeapAlloc: 49398605176 , HeapSys: 51807289344 , HeapInuse: 49567637504 , HeapIdle: 2239651840 , HeapReleased: 75153408 , HeapObjects: 113509344 , MSpanInuse: 135476808 , MCacheInuse: 3472 , StackSys: 753664 , NumGC: 24 , LastPauseGC: 17078396
m=+730.413530474 Bye!

A heap profile of our main app before it crashed with the OOM showed this behavior while consuming more and more memory:
ram_profile2.pdf
ram_profile3.pdf
ram_profile4.pdf
ram_profile5.pdf
ram_profile6.pdf

jarifibrahim commented :

@alexsporn This is great work. You’ve tuned most of the options appropriately. I have two more suggestions.

  1. Disable the cache (set MaxCacheSize=0) . The cache is used to store decrypted/decompressed blocks. Since you’re not using compression, the cache is not being used anyway.
  2. Use the Bloom filter cache https://github.com/dgraph-io/badger/blob/cddf7c03451c91e7a9c9df4121d16e1a56937786/options.go#L606-L620 Badger uses Bloom Filters to speed up the lookup speed and these bloom filters are stored in the memory. Each SST has a bf and each bloom filter takes up 5 MB. So 1896x5MB=9480MB (9.4GB). If the cache is enabled, the memory usage of the bloom filters should be bounded by the cache size.
    The cache might affect the read performance. Cache misses would be expensive because the bloom filter will have to read from the disk.

You can also disable the LoadBloomOnOpen https://github.com/dgraph-io/badger/blob/cddf7c03451c91e7a9c9df4121d16e1a56937786/options.go#L622-L633 This would reduce the time taken to start badger. But again, this would also affect the read performance as the bloom filters will be loaded on demand.

jarifibrahim commented :

@alexsporn You can monitor the Bloom Filter Cache Metrics https://godoc.org/github.com/dgraph-io/badger#DB.BfCacheMetrics to determine if the cache size should be increased. More cache misses mean slower reads.

alexsporn commented :

@jarifibrahim Thanks for the feedback, we will experiment with those values.

Any idea on the rapid memory consumption from my second comment? Where table.NewTableBuilder starts consuming lots and lots of memory?
Even just opening the database (using the provided sample code) after the OOM crash of the main app had a rapid memory increase

jarifibrahim commented :

@alexsporn The memory spike is very unusual. I see that profile shows 22GB of memory used by the table builder which a lot of memory. 22GB would hold 22000/67=328 SST. I don’t think there’s any way badger could be building 328 tables all at once. Can you share the badger logs? It might have some information about which level was being compacted.

imclaren commented :

Changing the badger options currently requires that users understand how the badger internals work. Providing sane medium memory and low memory defaults would be very useful.

For what it’s worth, changing the following option significantly reduced badger’s memory use for me:

opts := badger.DefaultOptions
opts.ValueLogLoadingMode = options.FileIO

And when the above change still uses too much memory, I currently use the following options for very low memory caches (on raspberrypi arm for example):

opts := badger.DefaultOptions
opts.TableLoadingMode, opts.ValueLogLoadingMode = options.FileIO, options.FileIO
opts.MaxTableSize = 1 << 20
opts.NumMemtables = 1
opts.NumLevelZeroTables = 1
opts.NumLevelZeroTablesStall = 2
opts.SyncWrites = false

I would be very interested to hear if I should be using different default options.

jarifibrahim commented :

@imclaren for very conservative memory usage, I would set the following options. Please be aware that memory usage and performance are inversely related. The less memory badger has, the slower your read/writes would be.

opts := badger.DefaultOptions
opts.TableLoadingMode = options.FileIO 
opts.ValueLogLoadingMode = options.FileIO

// Memtable size. This is the actively written in-memory data structure.
// This value also affects the size of a transaction. The size of a transaction is 15% of the table size.
opts.MaxTableSize = 1 << 20 
// To allow writes at a faster speed, we create a new memtable as soon as
// an existing memtable is filled up. This option determines how many
// memtables should be kept in memory.
opts.NumMemtables = 1

// This option will have a significant effect the memory. If the level is kept
// in-memory, read are faster but the tables will be kept in memory.
opts.KeepL0InMemory = false

// The NumLevelZeroTables and NumLevelZeroTableStall will not have any
// effect on the memory if `KeepL0InMemory` is set to false.
opts.NumLevelZeroTables = 1
opts.NumLevelZeroTablesStall = 2

// SyncWrites=false has significant effect on write performance. When sync
// writes is set to true, badger ensures the data is flushed to the disk after a
// write call. For normal usage, such a high level of consistency is not required.
opts.SyncWrites = false

// LoadBloomsOnOpen=false will improve the db startup speed
opts.LoadBloomsOnOpen=false

// Bloom filters will be kept in memory if the following option is not set. Each
// bloom filter takes up 5 MB of memory. A smaller bf cache would mean that
// bloom filters will be evicted quickly from the cache and they will be read from
// the disk (which is slow) and inserted into the cache.
opts.MaxBfCacheSize = 100 << 20

imclaren commented :

Thanks @jarifibrahim

Would it be worth updating the “Memory usage” section in readme, or adding these settings as badger.LowMemoryOptions ?

jarifibrahim commented :

@imclaren Yes! I think LowMemoryOptions would be useful to have.