Skip to content

Commit

Permalink
blockchain: Add CalculateMinEntries
Browse files Browse the repository at this point in the history
When allocating maps for Utxo caches, you may want to purposely allocate
a size thats lower than the one that'd fit in the memory limit.  Ex:
user gives a utxomaxcachesize of 1000MiB. You can allocate ~800MiB but
you may want to allocate ~400MiB to leave room for UtxoEntry sizes.
Having a function that returns the minimum amount of entries to allocate
~800MiB gives the caller the option to do -1 and allocate half as much
memory for the map.
  • Loading branch information
kcalvinalvin committed Mar 15, 2023
1 parent f42ff51 commit c2bf96c
Show file tree
Hide file tree
Showing 2 changed files with 46 additions and 0 deletions.
30 changes: 30 additions & 0 deletions blockchain/sizehelper.go
Original file line number Diff line number Diff line change
Expand Up @@ -129,6 +129,36 @@ func CalculateEntries(totalBytes int, bucketSize int) int {
return int(loadFactorNum * (bucketShift(B) / loadFactorDen))
}

// CalculateMinEntries returns the minimum number of entries that will make the
// map allocate the given total bytes. -1 on the returned entry count will
// make the map allocate half as much total bytes (for returned entry count that's
// greater than 0).
func CalculateMinEntries(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 < 4 {
switch B {
case 0:
return 0
case 1:
return 9
case 2:
return 14
default:
return 27
}
}

B -= 1

return (int(loadFactorNum * (bucketShift(B) / loadFactorDen))) + 1
}

// mulUintptr returns a * b and whether the multiplication overflowed.
// On supported platforms this is an intrinsic lowered by the compiler.
func mulUintptr(a, b uintptr) (uintptr, bool) {
Expand Down
16 changes: 16 additions & 0 deletions blockchain/sizehelper_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -29,5 +29,21 @@ func TestCalculateEntries(t *testing.T) {
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)
}
}
}
}

0 comments on commit c2bf96c

Please sign in to comment.