mirror of
https://github.com/ethereum/go-ethereum.git
synced 2026-08-20 10:52:25 +00:00
les: minCapacity calculation based on cpu and bandwidth limits
This commit is contained in:
parent
9bf2d758f3
commit
0f3222aaf0
5 changed files with 43 additions and 24 deletions
|
|
@ -206,12 +206,12 @@ var (
|
||||||
LightBandwidthInFlag = cli.IntFlag{
|
LightBandwidthInFlag = cli.IntFlag{
|
||||||
Name: "lightbwin",
|
Name: "lightbwin",
|
||||||
Usage: "Incoming bandwidth limit for light server (1000 bytes/sec, 0 = unlimited)",
|
Usage: "Incoming bandwidth limit for light server (1000 bytes/sec, 0 = unlimited)",
|
||||||
Value: 1000,
|
Value: 0,
|
||||||
}
|
}
|
||||||
LightBandwidthOutFlag = cli.IntFlag{
|
LightBandwidthOutFlag = cli.IntFlag{
|
||||||
Name: "lightbwout",
|
Name: "lightbwout",
|
||||||
Usage: "Outgoing bandwidth limit for light server (1000 bytes/sec, 0 = unlimited)",
|
Usage: "Outgoing bandwidth limit for light server (1000 bytes/sec, 0 = unlimited)",
|
||||||
Value: 5000,
|
Value: 0,
|
||||||
}
|
}
|
||||||
LightPeersFlag = cli.IntFlag{
|
LightPeersFlag = cli.IntFlag{
|
||||||
Name: "lightpeers",
|
Name: "lightpeers",
|
||||||
|
|
|
||||||
|
|
@ -101,7 +101,7 @@ func (s tcSubs) send(tc uint64, underrun bool) {
|
||||||
|
|
||||||
// MinimumCapacity queries minimum assignable capacity for a single client
|
// MinimumCapacity queries minimum assignable capacity for a single client
|
||||||
func (api *PrivateLightServerAPI) MinimumCapacity() hexutil.Uint64 {
|
func (api *PrivateLightServerAPI) MinimumCapacity() hexutil.Uint64 {
|
||||||
return hexutil.Uint64(minCapacity)
|
return hexutil.Uint64(api.server.minCapacity)
|
||||||
}
|
}
|
||||||
|
|
||||||
// FreeClientCapacity queries the capacity provided for free clients
|
// FreeClientCapacity queries the capacity provided for free clients
|
||||||
|
|
@ -117,7 +117,7 @@ func (api *PrivateLightServerAPI) FreeClientCapacity() hexutil.Uint64 {
|
||||||
// Note: assigned capacity can be changed while the client is connected with
|
// Note: assigned capacity can be changed while the client is connected with
|
||||||
// immediate effect.
|
// immediate effect.
|
||||||
func (api *PrivateLightServerAPI) SetClientCapacity(id enode.ID, cap uint64) error {
|
func (api *PrivateLightServerAPI) SetClientCapacity(id enode.ID, cap uint64) error {
|
||||||
if cap != 0 && cap < minCapacity {
|
if cap != 0 && cap < api.server.minCapacity {
|
||||||
return ErrMinCap
|
return ErrMinCap
|
||||||
}
|
}
|
||||||
return api.server.priorityClientPool.setClientCapacity(id, cap)
|
return api.server.priorityClientPool.setClientCapacity(id, cap)
|
||||||
|
|
|
||||||
|
|
@ -54,7 +54,7 @@ var (
|
||||||
GetCodeMsg: {0, 80},
|
GetCodeMsg: {0, 80},
|
||||||
GetProofsV2Msg: {0, 80},
|
GetProofsV2Msg: {0, 80},
|
||||||
GetHelperTrieProofsMsg: {0, 20},
|
GetHelperTrieProofsMsg: {0, 20},
|
||||||
SendTxV2Msg: {0, 66000},
|
SendTxV2Msg: {0, 16500},
|
||||||
GetTxStatusMsg: {0, 50},
|
GetTxStatusMsg: {0, 50},
|
||||||
}
|
}
|
||||||
// maximum outgoing message size estimates
|
// maximum outgoing message size estimates
|
||||||
|
|
@ -68,8 +68,18 @@ var (
|
||||||
SendTxV2Msg: {0, 100},
|
SendTxV2Msg: {0, 100},
|
||||||
GetTxStatusMsg: {0, 100},
|
GetTxStatusMsg: {0, 100},
|
||||||
}
|
}
|
||||||
minBufLimit = uint64(50000000 * maxCostFactor) // minimum buffer limit allowed for a client
|
// request amounts that have to fit into the minimum buffer size minBufferMultiplier times
|
||||||
minCapacity = (minBufLimit-1)/bufLimitRatio + 1 // minimum capacity allowed for a client
|
minBufferReqAmount = map[uint64]uint64{
|
||||||
|
GetBlockHeadersMsg: 192,
|
||||||
|
GetBlockBodiesMsg: 1,
|
||||||
|
GetReceiptsMsg: 1,
|
||||||
|
GetCodeMsg: 1,
|
||||||
|
GetProofsV2Msg: 1,
|
||||||
|
GetHelperTrieProofsMsg: 16,
|
||||||
|
SendTxV2Msg: 8,
|
||||||
|
GetTxStatusMsg: 64,
|
||||||
|
}
|
||||||
|
minBufferMultiplier = 3
|
||||||
)
|
)
|
||||||
|
|
||||||
const (
|
const (
|
||||||
|
|
@ -107,7 +117,7 @@ type costTracker struct {
|
||||||
}
|
}
|
||||||
|
|
||||||
// newCostTracker creates a cost tracker and loads the cost factor statistics from the database
|
// newCostTracker creates a cost tracker and loads the cost factor statistics from the database
|
||||||
func newCostTracker(db ethdb.Database, config *eth.Config, logger *csvlogger.Logger) *costTracker {
|
func newCostTracker(db ethdb.Database, config *eth.Config, logger *csvlogger.Logger) (*costTracker, uint64) {
|
||||||
utilTarget := float64(config.LightServ) * flowcontrol.FixedPointMultiplier / 100
|
utilTarget := float64(config.LightServ) * flowcontrol.FixedPointMultiplier / 100
|
||||||
ct := &costTracker{
|
ct := &costTracker{
|
||||||
db: db,
|
db: db,
|
||||||
|
|
@ -131,7 +141,18 @@ func newCostTracker(db ethdb.Database, config *eth.Config, logger *csvlogger.Log
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
ct.gfLoop()
|
ct.gfLoop()
|
||||||
return ct
|
costList := ct.makeCostList(ct.globalFactor() * 1.25)
|
||||||
|
var minBufLimit uint64
|
||||||
|
for _, c := range costList {
|
||||||
|
amount := minBufferReqAmount[c.MsgCode]
|
||||||
|
cost := c.BaseCost + amount*c.ReqCost
|
||||||
|
if cost > minBufLimit {
|
||||||
|
minBufLimit = cost
|
||||||
|
}
|
||||||
|
}
|
||||||
|
minBufLimit *= uint64(minBufferMultiplier)
|
||||||
|
minCapacity := (minBufLimit-1)/bufLimitRatio + 1
|
||||||
|
return ct, minCapacity
|
||||||
}
|
}
|
||||||
|
|
||||||
// stop stops the cost tracker and saves the cost factor statistics to the database
|
// stop stops the cost tracker and saves the cost factor statistics to the database
|
||||||
|
|
@ -146,16 +167,14 @@ func (ct *costTracker) stop() {
|
||||||
|
|
||||||
// makeCostList returns upper cost estimates based on the hardcoded cost estimate
|
// makeCostList returns upper cost estimates based on the hardcoded cost estimate
|
||||||
// tables and the optionally specified incoming/outgoing bandwidth limits
|
// tables and the optionally specified incoming/outgoing bandwidth limits
|
||||||
func (ct *costTracker) makeCostList() RequestCostList {
|
func (ct *costTracker) makeCostList(globalFactor float64) RequestCostList {
|
||||||
maxCost := func(avgTime, inSize, outSize uint64) uint64 {
|
maxCost := func(avgTime, inSize, outSize uint64) uint64 {
|
||||||
globalFactor := ct.globalFactor()
|
|
||||||
|
|
||||||
cost := avgTime * maxCostFactor
|
cost := avgTime * maxCostFactor
|
||||||
inSizeCost := uint64(float64(inSize) * ct.inSizeFactor * globalFactor * maxCostFactor)
|
inSizeCost := uint64(float64(inSize) * ct.inSizeFactor * globalFactor)
|
||||||
if inSizeCost > cost {
|
if inSizeCost > cost {
|
||||||
cost = inSizeCost
|
cost = inSizeCost
|
||||||
}
|
}
|
||||||
outSizeCost := uint64(float64(outSize) * ct.outSizeFactor * globalFactor * maxCostFactor)
|
outSizeCost := uint64(float64(outSize) * ct.outSizeFactor * globalFactor)
|
||||||
if outSizeCost > cost {
|
if outSizeCost > cost {
|
||||||
cost = outSizeCost
|
cost = outSizeCost
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -58,7 +58,7 @@ const (
|
||||||
// if the total encoded size of a sent transaction batch is over txSizeCostLimit
|
// if the total encoded size of a sent transaction batch is over txSizeCostLimit
|
||||||
// per transaction then the request cost is calculated as proportional to the
|
// per transaction then the request cost is calculated as proportional to the
|
||||||
// encoded size instead of the transaction count
|
// encoded size instead of the transaction count
|
||||||
const txSizeCostLimit = 0x10000
|
const txSizeCostLimit = 0x4000
|
||||||
|
|
||||||
const (
|
const (
|
||||||
announceTypeNone = iota
|
announceTypeNone = iota
|
||||||
|
|
@ -537,7 +537,7 @@ func (p *peer) Handshake(td *big.Int, head common.Hash, headNum uint64, genesis
|
||||||
send = send.add("flowControl/MRR", server.defParams.MinRecharge)
|
send = send.add("flowControl/MRR", server.defParams.MinRecharge)
|
||||||
var costList RequestCostList
|
var costList RequestCostList
|
||||||
if server.costTracker != nil {
|
if server.costTracker != nil {
|
||||||
costList = server.costTracker.makeCostList()
|
costList = server.costTracker.makeCostList(server.costTracker.globalFactor())
|
||||||
} else {
|
} else {
|
||||||
costList = testCostList()
|
costList = testCostList()
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -63,10 +63,10 @@ type LesServer struct {
|
||||||
|
|
||||||
thcNormal, thcBlockProcessing int // serving thread count for normal operation and block processing mode
|
thcNormal, thcBlockProcessing int // serving thread count for normal operation and block processing mode
|
||||||
|
|
||||||
maxPeers int
|
maxPeers int
|
||||||
freeClientCap uint64
|
minCapacity, freeClientCap uint64
|
||||||
freeClientPool *freeClientPool
|
freeClientPool *freeClientPool
|
||||||
priorityClientPool *priorityClientPool
|
priorityClientPool *priorityClientPool
|
||||||
}
|
}
|
||||||
|
|
||||||
func NewLesServer(eth *eth.Ethereum, config *eth.Config) (*LesServer, error) {
|
func NewLesServer(eth *eth.Ethereum, config *eth.Config) (*LesServer, error) {
|
||||||
|
|
@ -119,13 +119,13 @@ func NewLesServer(eth *eth.Ethereum, config *eth.Config) (*LesServer, error) {
|
||||||
bloomTrieIndexer: light.NewBloomTrieIndexer(eth.ChainDb(), nil, params.BloomBitsBlocks, params.BloomTrieFrequency),
|
bloomTrieIndexer: light.NewBloomTrieIndexer(eth.ChainDb(), nil, params.BloomBitsBlocks, params.BloomTrieFrequency),
|
||||||
protocolManager: pm,
|
protocolManager: pm,
|
||||||
},
|
},
|
||||||
costTracker: newCostTracker(eth.ChainDb(), config, requestLogger),
|
|
||||||
quitSync: quitSync,
|
quitSync: quitSync,
|
||||||
lesTopics: lesTopics,
|
lesTopics: lesTopics,
|
||||||
onlyAnnounce: config.OnlyAnnounce,
|
onlyAnnounce: config.OnlyAnnounce,
|
||||||
csvLogger: csvLogger,
|
csvLogger: csvLogger,
|
||||||
logTotalCap: requestLogger.NewChannel("totalCapacity", 0.01),
|
logTotalCap: requestLogger.NewChannel("totalCapacity", 0.01),
|
||||||
}
|
}
|
||||||
|
srv.costTracker, srv.minCapacity = newCostTracker(eth.ChainDb(), config, requestLogger)
|
||||||
|
|
||||||
logger := log.New()
|
logger := log.New()
|
||||||
pm.server = srv
|
pm.server = srv
|
||||||
|
|
@ -229,9 +229,9 @@ func (s *LesServer) Start(srvr *p2p.Server) {
|
||||||
s.maxPeers = s.config.LightPeers
|
s.maxPeers = s.config.LightPeers
|
||||||
totalRecharge := s.costTracker.totalRecharge()
|
totalRecharge := s.costTracker.totalRecharge()
|
||||||
if s.maxPeers > 0 {
|
if s.maxPeers > 0 {
|
||||||
s.freeClientCap = minCapacity //totalRecharge / uint64(s.maxPeers)
|
s.freeClientCap = s.minCapacity //totalRecharge / uint64(s.maxPeers)
|
||||||
if s.freeClientCap < minCapacity {
|
if s.freeClientCap < s.minCapacity {
|
||||||
s.freeClientCap = minCapacity
|
s.freeClientCap = s.minCapacity
|
||||||
}
|
}
|
||||||
if s.freeClientCap > 0 {
|
if s.freeClientCap > 0 {
|
||||||
s.defParams = flowcontrol.ServerParams{
|
s.defParams = flowcontrol.ServerParams{
|
||||||
|
|
|
||||||
Loading…
Reference in a new issue