github.com/btcsuite/btcd@v0.24.0/blockchain/sizehelper_test.go (about) 1 // Copyright (c) 2023 The btcsuite developers 2 // Use of this source code is governed by an ISC 3 // license that can be found in the LICENSE file. 4 package blockchain 5 6 import ( 7 "math" 8 "testing" 9 ) 10 11 // calculateEntries returns a number of entries that will make the map allocate 12 // the given total bytes. The returned number is always the maximum number of 13 // entries that will allocate inside the given parameters. 14 func calculateEntries(totalBytes int, bucketSize int) int { 15 // 48 is the number of bytes needed for the map header in a 16 // 64 bit system. Refer to hmap in runtime/map.go in the go 17 // standard library. 18 totalBytes -= 48 19 20 numBuckets := totalBytes / bucketSize 21 B := uint8(math.Log2(float64(numBuckets))) 22 if B == 0 { 23 // For 0 buckets, the max is the bucket count. 24 return bucketCnt 25 } 26 27 return int(loadFactorNum * (bucketShift(B) / loadFactorDen)) 28 } 29 30 func TestCalculateEntries(t *testing.T) { 31 for i := 0; i < 10_000_000; i++ { 32 // It's not possible to calculate the exact amount of entries since 33 // the map will only allocate for 2^N where N is the amount of buckets. 34 // 35 // So to see if the calculate entries function is working correctly, 36 // we get the rough map size for i entries, then calculate the entries 37 // for that map size. If the size is the same, the function is correct. 38 roughMapSize := calculateRoughMapSize(i, bucketSize) 39 entries := calculateEntries(roughMapSize, bucketSize) 40 gotRoughMapSize := calculateRoughMapSize(entries, bucketSize) 41 42 if roughMapSize != gotRoughMapSize { 43 t.Errorf("For hint of %d, expected %v, got %v\n", 44 i, roughMapSize, gotRoughMapSize) 45 } 46 47 // Test that the entries returned are the maximum for the given map size. 48 // If we increment the entries by one, we should get a bigger map. 49 gotRoughMapSizeWrong := calculateRoughMapSize(entries+1, bucketSize) 50 if roughMapSize == gotRoughMapSizeWrong { 51 t.Errorf("For hint %d incremented by 1, expected %v, got %v\n", 52 i, gotRoughMapSizeWrong*2, gotRoughMapSizeWrong) 53 } 54 55 minEntries := calculateMinEntries(roughMapSize, bucketSize) 56 gotMinRoughMapSize := calculateRoughMapSize(minEntries, bucketSize) 57 if roughMapSize != gotMinRoughMapSize { 58 t.Errorf("For hint of %d, expected %v, got %v\n", 59 i, roughMapSize, gotMinRoughMapSize) 60 } 61 62 // Can only test if they'll be half the size if the entries aren't 0. 63 if minEntries > 0 { 64 gotMinRoughMapSizeWrong := calculateRoughMapSize(minEntries-1, bucketSize) 65 if gotMinRoughMapSize == gotMinRoughMapSizeWrong { 66 t.Errorf("For hint %d decremented by 1, expected %v, got %v\n", 67 i, gotRoughMapSizeWrong/2, gotRoughMapSizeWrong) 68 } 69 } 70 } 71 }