btcd/blockchain/sizehelper_test.go

72 lines
2.6 KiB
Go
Raw Normal View History

// Copyright (c) 2023 The btcsuite developers
// Use of this source code is governed by an ISC
// license that can be found in the LICENSE file.
package blockchain
import (
"math"
"testing"
)
// calculateEntries returns a number of entries that will make the map allocate
// the given total bytes. The returned number is always the maximum number of
// entries that will allocate inside the given parameters.
func calculateEntries(totalBytes int, bucketSize int) int {
// 48 is the number of bytes needed for the map header in a
// 64 bit system. Refer to hmap in runtime/map.go in the go
// standard library.
totalBytes -= 48
numBuckets := totalBytes / bucketSize
B := uint8(math.Log2(float64(numBuckets)))
if B == 0 {
// For 0 buckets, the max is the bucket count.
return bucketCnt
}
return int(loadFactorNum * (bucketShift(B) / loadFactorDen))
}
func TestCalculateEntries(t *testing.T) {
for i := 0; i < 10_000_000; i++ {
// It's not possible to calculate the exact amount of entries since
// the map will only allocate for 2^N where N is the amount of buckets.
//
// So to see if the calculate entries function is working correctly,
// we get the rough map size for i entries, then calculate the entries
// for that map size. If the size is the same, the function is correct.
roughMapSize := calculateRoughMapSize(i, bucketSize)
entries := calculateEntries(roughMapSize, bucketSize)
gotRoughMapSize := calculateRoughMapSize(entries, bucketSize)
if roughMapSize != gotRoughMapSize {
t.Errorf("For hint of %d, expected %v, got %v\n",
i, roughMapSize, gotRoughMapSize)
}
// Test that the entries returned are the maximum for the given map size.
// If we increment the entries by one, we should get a bigger map.
gotRoughMapSizeWrong := calculateRoughMapSize(entries+1, bucketSize)
if roughMapSize == gotRoughMapSizeWrong {
t.Errorf("For hint %d incremented by 1, expected %v, got %v\n",
i, gotRoughMapSizeWrong*2, gotRoughMapSizeWrong)
}
minEntries := calculateMinEntries(roughMapSize, bucketSize)
gotMinRoughMapSize := calculateRoughMapSize(minEntries, bucketSize)
if roughMapSize != gotMinRoughMapSize {
t.Errorf("For hint of %d, expected %v, got %v\n",
i, roughMapSize, gotMinRoughMapSize)
}
// Can only test if they'll be half the size if the entries aren't 0.
if minEntries > 0 {
gotMinRoughMapSizeWrong := calculateRoughMapSize(minEntries-1, bucketSize)
if gotMinRoughMapSize == gotMinRoughMapSizeWrong {
t.Errorf("For hint %d decremented by 1, expected %v, got %v\n",
i, gotRoughMapSizeWrong/2, gotRoughMapSizeWrong)
}
}
}
}