Optimize PPLNS window iteration, remove pprof context

This commit is contained in:
DataHoarder 2023-07-26 14:18:45 +02:00
parent 65747205dd
commit 466f2ce1f2
Signed by: DataHoarder
SSH key fingerprint: SHA256:OLTRf6Fl87G52SiR7sWLGNzlJt4WOX+tfI2yxo0z7xk
4 changed files with 125 additions and 77 deletions

View file

@ -28,7 +28,6 @@ import (
"net/netip"
"net/url"
"os"
"runtime/pprof"
"slices"
"strconv"
"strings"
@ -179,7 +178,7 @@ func main() {
var pplnsWeight types.Difficulty
if err := index.IterateSideBlocksInPPLNSWindow(tip, consensus, indexDb.GetDifficultyByHeight, indexDb.GetTipSideBlockByTemplateId, indexDb.GetSideBlocksByUncleOfId, func(b *index.SideBlock, weight types.Difficulty) {
if err := index.IterateSideBlocksInPPLNSWindowFast(indexDb, tip, indexDb.GetDifficultyByHeight, func(b *index.SideBlock, weight types.Difficulty) {
miners[indexDb.GetMiner(b.Miner).Id()]++
pplnsWeight = pplnsWeight.Add(weight)
@ -1905,15 +1904,7 @@ func main() {
return
}
pathEntry := "/"
splitPath := strings.Split(request.URL.Path, "/")
if len(splitPath) > 1 {
pathEntry = splitPath[1]
}
pprof.Do(request.Context(), pprof.Labels("path", pathEntry), func(ctx context.Context) {
serveMux.ServeHTTP(writer, request)
})
serveMux.ServeHTTP(writer, request)
}),
}

View file

@ -107,63 +107,9 @@ func Outputs(p2api *api.P2PoolApi, indexDb *index.Index, tip *index.SideBlock, d
}
func PayoutHint(p2api *api.P2PoolApi, indexDb *index.Index, tip *index.SideBlock) (shares map[uint64]types.Difficulty, blockDepth uint64) {
if tip == nil {
return nil, 0
}
window := index.QueryIterateToSlice(indexDb.GetSideBlocksInPPLNSWindow(tip))
if len(window) == 0 {
return nil, 0
}
shares = make(map[uint64]types.Difficulty)
var hintIndex int
getByTemplateIdFull := func(h types.Hash) *index.SideBlock {
if i := slices.IndexFunc(window, func(e *index.SideBlock) bool {
return e.TemplateId == h
}); i != -1 {
hintIndex = i
return window[i]
}
return nil
}
getByTemplateId := func(h types.Hash) *index.SideBlock {
//fast lookup first
if i := slices.IndexFunc(window[hintIndex:], func(e *index.SideBlock) bool {
return e.TemplateId == h
}); i != -1 {
hintIndex += i
return window[hintIndex]
}
return getByTemplateIdFull(h)
}
getUnclesOf := func(h types.Hash) index.QueryIterator[index.SideBlock] {
parentEffectiveHeight := window[hintIndex].EffectiveHeight
if window[hintIndex].TemplateId != h {
parentEffectiveHeight = 0
}
startIndex := 0
return &index.FakeQueryResult[index.SideBlock]{
NextFunction: func() (int, *index.SideBlock) {
for _, b := range window[startIndex+hintIndex:] {
if b.UncleOf == h {
startIndex++
return startIndex, b
}
startIndex++
if parentEffectiveHeight != 0 && b.EffectiveHeight < parentEffectiveHeight {
//early exit
break
}
}
return 0, nil
},
}
}
blockDepth, err := index.BlocksInPPLNSWindow(tip, indexDb.Consensus(), p2api.MainDifficultyByHeight, getByTemplateId, getUnclesOf, func(b *index.SideBlock, weight types.Difficulty) {
blockDepth, err := index.BlocksInPPLNSWindowFast(indexDb, tip, p2api.MainDifficultyByHeight, func(b *index.SideBlock, weight types.Difficulty) {
if _, ok := shares[b.Miner]; !ok {
shares[b.Miner] = types.DifficultyFrom64(0)
}

View file

@ -1,6 +1,7 @@
package index
import (
"errors"
"fmt"
"git.gammaspectra.live/P2Pool/p2pool-observer/monero/block"
"git.gammaspectra.live/P2Pool/p2pool-observer/monero/crypto"
@ -231,6 +232,126 @@ func BlocksInPPLNSWindow(tip *SideBlock, consensus *sidechain.Consensus, difficu
return bottomHeight, nil
}
func IterateSideBlocksInPPLNSWindowFast(indexDb *Index, tip *SideBlock, difficultyByHeight block.GetDifficultyByHeightFunc, addWeightFunc SideBlockWindowAddWeightFunc, slotFunc func(slot SideBlockWindowSlot)) error {
if tip == nil {
return errors.New("nil tip")
}
window := QueryIterateToSlice(indexDb.GetSideBlocksInPPLNSWindow(tip))
if len(window) == 0 {
return errors.New("nil window")
}
var hintIndex int
getByTemplateIdFull := func(h types.Hash) *SideBlock {
if i := slices.IndexFunc(window, func(e *SideBlock) bool {
return e.TemplateId == h
}); i != -1 {
hintIndex = i
return window[i]
}
return nil
}
getByTemplateId := func(h types.Hash) *SideBlock {
//fast lookup first
if i := slices.IndexFunc(window[hintIndex:], func(e *SideBlock) bool {
return e.TemplateId == h
}); i != -1 {
hintIndex += i
return window[hintIndex]
}
return getByTemplateIdFull(h)
}
getUnclesOf := func(h types.Hash) QueryIterator[SideBlock] {
parentEffectiveHeight := window[hintIndex].EffectiveHeight
if window[hintIndex].TemplateId != h {
parentEffectiveHeight = 0
}
startIndex := 0
return &FakeQueryResult[SideBlock]{
NextFunction: func() (int, *SideBlock) {
for _, b := range window[startIndex+hintIndex:] {
if b.UncleOf == h {
startIndex++
return startIndex, b
}
startIndex++
if parentEffectiveHeight != 0 && b.EffectiveHeight < parentEffectiveHeight {
//early exit
break
}
}
return 0, nil
},
}
}
return IterateSideBlocksInPPLNSWindow(tip, indexDb.Consensus(), difficultyByHeight, getByTemplateId, getUnclesOf, addWeightFunc, slotFunc)
}
func BlocksInPPLNSWindowFast(indexDb *Index, tip *SideBlock, difficultyByHeight block.GetDifficultyByHeightFunc, addWeightFunc SideBlockWindowAddWeightFunc) (bottomHeight uint64, err error) {
if tip == nil {
return 0, errors.New("nil tip")
}
window := QueryIterateToSlice(indexDb.GetSideBlocksInPPLNSWindow(tip))
if len(window) == 0 {
return 0, errors.New("nil window")
}
var hintIndex int
getByTemplateIdFull := func(h types.Hash) *SideBlock {
if i := slices.IndexFunc(window, func(e *SideBlock) bool {
return e.TemplateId == h
}); i != -1 {
hintIndex = i
return window[i]
}
return nil
}
getByTemplateId := func(h types.Hash) *SideBlock {
//fast lookup first
if i := slices.IndexFunc(window[hintIndex:], func(e *SideBlock) bool {
return e.TemplateId == h
}); i != -1 {
hintIndex += i
return window[hintIndex]
}
return getByTemplateIdFull(h)
}
getUnclesOf := func(h types.Hash) QueryIterator[SideBlock] {
parentEffectiveHeight := window[hintIndex].EffectiveHeight
if window[hintIndex].TemplateId != h {
parentEffectiveHeight = 0
}
startIndex := 0
return &FakeQueryResult[SideBlock]{
NextFunction: func() (int, *SideBlock) {
for _, b := range window[startIndex+hintIndex:] {
if b.UncleOf == h {
startIndex++
return startIndex, b
}
startIndex++
if parentEffectiveHeight != 0 && b.EffectiveHeight < parentEffectiveHeight {
//early exit
break
}
}
return 0, nil
},
}
}
return BlocksInPPLNSWindow(tip, indexDb.Consensus(), difficultyByHeight, getByTemplateId, getUnclesOf, addWeightFunc)
}
// GetSharesOrdered
// Copy of sidechain.GetSharesOrdered
func GetSharesOrdered(indexDb *Index, tip *SideBlock, difficultyByHeight block.GetDifficultyByHeightFunc, getByTemplateId GetByTemplateIdFunc, getUnclesByTemplateId GetUnclesByTemplateIdFunc, preAllocatedShares sidechain.Shares) (shares sidechain.Shares, bottomHeight uint64) {

View file

@ -2,7 +2,6 @@ package main
import (
"bytes"
"context"
"flag"
"fmt"
"git.gammaspectra.live/P2Pool/p2pool-observer/cmd/index"
@ -26,7 +25,6 @@ import (
"net/netip"
"net/url"
"os"
"runtime/pprof"
"slices"
"strconv"
"strings"
@ -1154,15 +1152,7 @@ func main() {
writer.Header().Set("content-type", "text/html; charset=utf-8")
pathEntry := "/"
splitPath := strings.Split(request.URL.Path, "/")
if len(splitPath) > 1 {
pathEntry = splitPath[1]
}
pprof.Do(request.Context(), pprof.Labels("path", pathEntry), func(ctx context.Context) {
serveMux.ServeHTTP(writer, request)
})
serveMux.ServeHTTP(writer, request)
}),
}