Unable to Get values while using Ristrettro Cache

Hi,
I’m trying to use Ristrettro for my application. While writing the benchmarks for comparison, I’m facing an issue where the Get is not able to find the value even after a time.Sleep(10 * time.Millisecond)
My use case is - At first, I’m setting a lot of values with SetWithTTL and then after some sleep time in between, I’m trying to Get those values. That’s where its failing.
My Benchmark is as follows :

func BenchmarkCacheSetWithRistretto(b *testing.B) {
	cache, err := ristretto.NewCache(&ristretto.Config{
		NumCounters: 10000000 * 10,
		MaxCost:     10000000,    
		BufferItems: 64,           
	})
	if err != nil {
		panic(err)
	}

	for n := 0; n < b.N; n++ {
		cache.SetWithTTL(strconv.Itoa(n%1000000)+strconv.Itoa(n%1000000), "value", 1, time.Duration(5*time.Second))
	}
	time.Sleep(50 * time.Millisecond)

	for n := 0; n < b.N; n++ {
		_, found := cache.Get(strconv.Itoa(n%1000000) + strconv.Itoa(n%1000000))
		if !found {
			panic("Value not found.")
		}
	}
}

I think you should use some other values to fill the cache and not use the iterator per-se.

Also I guess it is not failing for all values but some n, right?

1 Like

What do you suggest I use if not the iterator? I need to ensure there are many different keys in the map.

The issue is that iterators in these loops (ones used for benchmarking) are non-deterministic.
Quoting from here:

Each benchmark is run for a minimum of 1 second by default. If the second has not elapsed when the Benchmark function returns, the value of b.N is increased in the sequence 1, 2, 5, 10, 20, 50, … and the function run again.

What you could potentially do is something like this:

And similarly search for all the keys when you are benchmarking the get part of the code.

@Anurag But since I’m running both the iteration in the same benchmark, the value of b.n shouldn’t vary, right?
Tried setting a fixed bound myself. Did not work.

I think you should not run these two loops inside one function. Can you take a look at this file here, where I try to do something similar inside two sub-benchmarks?

To answer your question, b.N is adjusted based on how much time the code inside that loop takes to run for one iteration. Therefore it need not be same if you nest two different things inside this loop.

@Anurag @muskan_sethia The value of b.N remains the same in one iteration. So the benchmark written is fine.

The value is missing after sets because ristretto can choose to drop keys in case of a high load. The setbuf here ristretto/cache.go at 8f368f2f2ab3a54cbe62fb9772cd75ce55e07802 · dgraph-io/ristretto · GitHub will drop keys if there is high load (like a benchmark)

@muskan_sethia The following benchmark runs fine. Set slowInsertions if you don’t want cache to drop anything.

func BenchmarkCacheSetWithRistretto(b *testing.B) {
	cache, err := ristretto.NewCache(&ristretto.Config{
		NumCounters: 10000000 * 10,
		MaxCost:     10000000,
		BufferItems: 64,
	})
	if err != nil {
		panic(err)
	}

	failedSets := 0

	// Set slow insertions if you want all the entries to be inserted.
	slowInsertions := true
	for n := 0; n < b.N; n++ {

		if slowInsertions {
			time.Sleep(time.Microsecond)
		}
		key := strconv.Itoa(n%1000000) + strconv.Itoa(n%1000000)
		// Cache.Set returns a boolean denoting if the set was successful or
		// not. The cache can choose to drop keys in times of high load.
		if !cache.SetWithTTL(key, "value", 1, time.Duration(5*time.Second)) {
			failedSets++
		}
	}
	// All sets should be succesful if we're inserting slowing.
	if slowInsertions {
		require.Zero(b, failedSets)
	}
	time.Sleep(50 * time.Millisecond)

	notFoundCount := 0
	for n := 0; n < b.N; n++ {
		_, found := cache.Get(strconv.Itoa(n%1000000) + strconv.Itoa(n%1000000))
		if !found {
			notFoundCount++
		}
	}
	require.Equal(b, failedSets, notFoundCount)
}
1 Like

Thanks, ibrahim. I understand now why the Sets were getting dropped.
slowInsertions works but it essentially delays the number of operations of the Benchmark since this time is also added to the delay. I will see how I can remove that time delay from benchmark results during Set.

@muskan_sethia you might want to look at benchmarks/cachebench/ristretto at master · dgraph-io/benchmarks · GitHub . These are the benchmarks for ristretto.

I will do that, Thanks!