Skip to content

Commit

Permalink
utxocache: pre-size cache to max element size
Browse files Browse the repository at this point in the history
In this commit, we pre-allocate our cache to hold the maximum number of
entries possible. We do this for two reasons:

  1. Go maps do not shrink when items are deleted from there, so we'll
  end up with a map of this size anyway.

  2. By doing our large allocation, we avoid doing many smaller
  allocations causing more GC pressure as we ramp up to our max cache
  size.

To estimate the max size of the cache, we use the length of a p2pkh
script since they're larger than p2wkh scripts, and p2wkh isn't as
widespread yet.
  • Loading branch information
Roasbeef committed Jan 18, 2019
1 parent cef1899 commit 18bd81f
Showing 1 changed file with 15 additions and 10 deletions.
25 changes: 15 additions & 10 deletions blockchain/utxocache.go
Original file line number Diff line number Diff line change
Expand Up @@ -31,6 +31,17 @@ const (
// utxoFlushPeriodicThreshold is the threshold percentage at which a flush is
// performed when the flush mode FlushPeriodic is used.
utxoFlushPeriodicThreshold = 90

// This value is calculated by running the following on a 64-bit system:
// unsafe.Sizeof(UtxoEntry{})
baseEntrySize = uint64(40)

// This value is calculated by running the following on a 64-bit system:
// unsafe.Sizeof(wire.OutPoint{})
outpointSize = uint64(36)

// pubKeyHashLen is the length of a P2PKH script.
pubKeyHashLen = 25
)

// txoFlags is a bitmask defining additional information and state for a
Expand Down Expand Up @@ -125,10 +136,6 @@ func (entry *UtxoEntry) memoryUsage() uint64 {
return 0
}

// This value is calculated by running the following on a 64-bit system:
// unsafe.Sizeof(UtxoEntry{})
baseEntrySize := uint64(40)

return baseEntrySize + uint64(len(entry.pkScript))
}

Expand Down Expand Up @@ -209,22 +216,20 @@ type utxoCache struct {
// newUtxoCache initiates a new utxo cache instance with its memory usage limited
// to the given maximum.
func newUtxoCache(db database.DB, maxTotalMemoryUsage uint64) *utxoCache {
avgEntrySize := outpointSize + 8 + baseEntrySize + pubKeyHashLen
numMaxElements := maxTotalMemoryUsage / avgEntrySize
log.Info("Pre-alloacting for %v entries: ", numMaxElements)
return &utxoCache{
db: db,
maxTotalMemoryUsage: maxTotalMemoryUsage,

cachedEntries: make(map[wire.OutPoint]*UtxoEntry),
cachedEntries: make(map[wire.OutPoint]*UtxoEntry, numMaxElements),
}
}

// totalMemoryUsage returns the total memory usage in bytes of the UTXO cache.
//
// This method should be called with the state lock held.
func (s *utxoCache) totalMemoryUsage() uint64 {
// This value is calculated by running the following on a 64-bit system:
// unsafe.Sizeof(wire.OutPoint{})
outpointSize := uint64(36)

// Total memory is all the keys plus the total memory of all the entries.
nbEntries := uint64(len(s.cachedEntries))

Expand Down

0 comments on commit 18bd81f

Please sign in to comment.