Implement utils.NthElementSlice to use QuickSelect, improves GetDifficulty

This commit is contained in:
DataHoarder 2023-07-04 20:28:54 +02:00
parent 90184b07cc
commit 152cbc54c2
Signed by: DataHoarder
SSH key fingerprint: SHA256:OLTRf6Fl87G52SiR7sWLGNzlJt4WOX+tfI2yxo0z7xk
2 changed files with 51 additions and 10 deletions

View file

@ -354,6 +354,10 @@ func GetDifficulty(tip *PoolBlock, consensus *Consensus, getByTemplateId GetByTe
Timestamp: cur.Main.Timestamp,
})
if cur.Main.Timestamp < oldestTimestamp {
oldestTimestamp = cur.Main.Timestamp
}
if err := cur.iteratorUncles(getByTemplateId, func(uncle *PoolBlock) {
// Skip uncles which are already out of PPLNS window
if (tip.Side.Height - uncle.Side.Height) >= consensus.ChainWindowSize {
@ -364,6 +368,10 @@ func GetDifficulty(tip *PoolBlock, consensus *Consensus, getByTemplateId GetByTe
CumulativeDifficulty: uncle.Side.CumulativeDifficulty,
Timestamp: uncle.Main.Timestamp,
})
if uncle.Main.Timestamp < oldestTimestamp {
oldestTimestamp = uncle.Main.Timestamp
}
}); err != nil {
return types.ZeroDifficulty, err, nil
}
@ -387,12 +395,6 @@ func GetDifficulty(tip *PoolBlock, consensus *Consensus, getByTemplateId GetByTe
}
}
for i := range difficultyData {
if difficultyData[i].Timestamp < oldestTimestamp {
oldestTimestamp = difficultyData[i].Timestamp
}
}
tmpTimestamps := preAllocatedTimestampDifferences[:0]
// Discard 10% oldest and 10% newest (by timestamp) blocks
@ -404,10 +406,10 @@ func GetDifficulty(tip *PoolBlock, consensus *Consensus, getByTemplateId GetByTe
lowIndex := cutSize - 1
upperIndex := len(difficultyData) - cutSize
//TODO: replace this with introspective selection, use order for now
slices.Sort(tmpTimestamps)
utils.NthElementSlice(tmpTimestamps, lowIndex)
timestampLowerBound := oldestTimestamp + uint64(tmpTimestamps[lowIndex])
utils.NthElementSlice(tmpTimestamps, upperIndex)
timestampUpperBound := oldestTimestamp + uint64(tmpTimestamps[upperIndex])
// Make a reasonable assumption that each block has higher timestamp, so deltaTimestamp can't be less than deltaIndex

View file

@ -1,9 +1,48 @@
package utils
import "slices"
import (
"cmp"
"slices"
)
func ReverseSlice[S ~[]E, E any](s S) S {
slices.Reverse(s)
return s
}
// NthElementSlice QuickSelect implementation
// k is the desired index value, where array[k] is the k+1 smallest element
func NthElementSlice[S ~[]E, E cmp.Ordered](s S, k int) {
left := 0
right := len(s) - 1
for {
if left == right {
return
}
pivotIndex := (left + right) >> 1 // Use middle point as pivot. This could probably use random index
pivotIndex = partition(s, pivotIndex, left, right)
if k == pivotIndex {
return
} else if k < pivotIndex {
right = pivotIndex - 1
} else {
left = pivotIndex + 1
}
}
}
// Partition values into less than s[pivot] and greater than s[pivot]
func partition[S ~[]E, E cmp.Ordered](s S, pivot, left, right int) int {
s[pivot], s[right] = s[right], s[pivot] // Move pivot to end
storeIndex := left
for i := left; i < right; i++ {
if s[i] < s[right] { // Compare to pivot value
s[storeIndex], s[i] = s[i], s[storeIndex]
storeIndex++
}
}
s[right], s[storeIndex] = s[storeIndex], s[right] // Return pivot Index to position
return storeIndex
}