Implement utils.NthElementSlice to use QuickSelect, improves GetDifficulty
This commit is contained in:
parent
90184b07cc
commit
152cbc54c2
|
@ -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
|
||||
|
|
|
@ -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
|
||||
}
|
||||
|
|
Loading…
Reference in a new issue