mirror of
https://github.com/ethereum/go-ethereum.git
synced 2026-08-20 10:52:25 +00:00
les: renamed bandwidth to capacity
This commit is contained in:
parent
8ac0362647
commit
3421811582
8 changed files with 109 additions and 109 deletions
40
les/api.go
40
les/api.go
|
|
@ -24,8 +24,8 @@ import (
|
||||||
)
|
)
|
||||||
|
|
||||||
var (
|
var (
|
||||||
ErrMinBW = errors.New("bandwidth too small")
|
ErrMinBW = errors.New("capacity too small")
|
||||||
ErrTotalBW = errors.New("total bandwidth exceeded")
|
ErrTotalBW = errors.New("total capacity exceeded")
|
||||||
)
|
)
|
||||||
|
|
||||||
// PublicLesServerAPI provides an API to access the les server.
|
// PublicLesServerAPI provides an API to access the les server.
|
||||||
|
|
@ -40,7 +40,7 @@ type PrivateLesServerAPI struct {
|
||||||
func NewPrivateLesServerAPI(server *LesServer) *PrivateLesServerAPI {
|
func NewPrivateLesServerAPI(server *LesServer) *PrivateLesServerAPI {
|
||||||
vip := &vipClientPool{
|
vip := &vipClientPool{
|
||||||
clients: make(map[enode.ID]vipClientInfo),
|
clients: make(map[enode.ID]vipClientInfo),
|
||||||
totalBw: server.totalBandwidth,
|
totalBw: server.totalCapacity,
|
||||||
pm: server.protocolManager,
|
pm: server.protocolManager,
|
||||||
}
|
}
|
||||||
server.protocolManager.vipClientPool = vip
|
server.protocolManager.vipClientPool = vip
|
||||||
|
|
@ -51,14 +51,14 @@ func NewPrivateLesServerAPI(server *LesServer) *PrivateLesServerAPI {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// TotalBandwidth queries total available bandwidth for all clients
|
// TotalCapacity queries total available capacity for all clients
|
||||||
func (api *PrivateLesServerAPI) TotalBandwidth() hexutil.Uint64 {
|
func (api *PrivateLesServerAPI) TotalCapacity() hexutil.Uint64 {
|
||||||
return hexutil.Uint64(api.server.totalBandwidth)
|
return hexutil.Uint64(api.server.totalCapacity)
|
||||||
}
|
}
|
||||||
|
|
||||||
// MinimumBandwidth queries minimum assignable bandwidth for a single client
|
// MinimumCapacity queries minimum assignable capacity for a single client
|
||||||
func (api *PrivateLesServerAPI) MinimumBandwidth() hexutil.Uint64 {
|
func (api *PrivateLesServerAPI) MinimumCapacity() hexutil.Uint64 {
|
||||||
return hexutil.Uint64(api.server.minBandwidth)
|
return hexutil.Uint64(api.server.minCapacity)
|
||||||
}
|
}
|
||||||
|
|
||||||
// vipClientPool stores information about prioritized clients
|
// vipClientPool stores information about prioritized clients
|
||||||
|
|
@ -77,15 +77,15 @@ type vipClientInfo struct {
|
||||||
updateBw func(uint64)
|
updateBw func(uint64)
|
||||||
}
|
}
|
||||||
|
|
||||||
// SetClientBandwidth sets the priority bandwidth assigned to a given client.
|
// SetClientCapacity sets the priority capacity assigned to a given client.
|
||||||
// If the assigned bandwidth is bigger than zero then connection is always
|
// If the assigned capacity is bigger than zero then connection is always
|
||||||
// guaranteed. The sum of bandwidth assigned to priority clients can not exceed
|
// guaranteed. The sum of capacity assigned to priority clients can not exceed
|
||||||
// the total available bandwidth.
|
// the total available capacity.
|
||||||
//
|
//
|
||||||
// Note: assigned bandwidth 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 *PrivateLesServerAPI) SetClientBandwidth(id enode.ID, bw uint64) error {
|
func (api *PrivateLesServerAPI) SetClientCapacity(id enode.ID, bw uint64) error {
|
||||||
if bw != 0 && bw < api.server.minBandwidth {
|
if bw != 0 && bw < api.server.minCapacity {
|
||||||
return ErrMinBW
|
return ErrMinBW
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -122,8 +122,8 @@ func (api *PrivateLesServerAPI) SetClientBandwidth(id enode.ID, bw uint64) error
|
||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
|
|
||||||
// GetClientBandwidth returns the bandwidth assigned to a given client
|
// GetClientCapacity returns the capacity assigned to a given client
|
||||||
func (api *PrivateLesServerAPI) GetClientBandwidth(id enode.ID) hexutil.Uint64 {
|
func (api *PrivateLesServerAPI) GetClientCapacity(id enode.ID) hexutil.Uint64 {
|
||||||
api.vip.lock.Lock()
|
api.vip.lock.Lock()
|
||||||
defer api.vip.lock.Unlock()
|
defer api.vip.lock.Unlock()
|
||||||
|
|
||||||
|
|
@ -131,8 +131,8 @@ func (api *PrivateLesServerAPI) GetClientBandwidth(id enode.ID) hexutil.Uint64 {
|
||||||
}
|
}
|
||||||
|
|
||||||
// connect should be called when a new client is connected. The callback function
|
// connect should be called when a new client is connected. The callback function
|
||||||
// is called when the assigned bandwidth is changed while the client is connected.
|
// is called when the assigned capacity is changed while the client is connected.
|
||||||
// It returns the priority bandwidth or zero if the client is not prioritized.
|
// It returns the priority capacity or zero if the client is not prioritized.
|
||||||
// It also returns whether the client can be accepted.
|
// It also returns whether the client can be accepted.
|
||||||
//
|
//
|
||||||
// Note: vipClientPool also stores a record about free clients while they are
|
// Note: vipClientPool also stores a record about free clients while they are
|
||||||
|
|
|
||||||
|
|
@ -52,33 +52,33 @@ request performance test. When testServerDataDir is empty, the test is skipped.
|
||||||
|
|
||||||
const (
|
const (
|
||||||
testServerDataDir = "" // should always be empty on the master branch
|
testServerDataDir = "" // should always be empty on the master branch
|
||||||
testServerBandwidth = 200
|
testServerCapacity = 200
|
||||||
testMaxClients = 10
|
testMaxClients = 10
|
||||||
testTolerance = 0.1
|
testTolerance = 0.1
|
||||||
minRelBw = 0.2
|
minRelBw = 0.2
|
||||||
)
|
)
|
||||||
|
|
||||||
func TestBandwidthAPI3(t *testing.T) {
|
func TestCapacityAPI3(t *testing.T) {
|
||||||
testBandwidthAPI(t, 3)
|
testCapacityAPI(t, 3)
|
||||||
}
|
}
|
||||||
|
|
||||||
func TestBandwidthAPI6(t *testing.T) {
|
func TestCapacityAPI6(t *testing.T) {
|
||||||
testBandwidthAPI(t, 6)
|
testCapacityAPI(t, 6)
|
||||||
}
|
}
|
||||||
|
|
||||||
func TestBandwidthAPI10(t *testing.T) {
|
func TestCapacityAPI10(t *testing.T) {
|
||||||
testBandwidthAPI(t, 10)
|
testCapacityAPI(t, 10)
|
||||||
}
|
}
|
||||||
|
|
||||||
// testBandwidthAPI runs an end-to-end simulation test connecting one server with
|
// testCapacityAPI runs an end-to-end simulation test connecting one server with
|
||||||
// a given number of clients. It sets different priority bandwidths to all clients
|
// a given number of clients. It sets different priority capacitys to all clients
|
||||||
// except a randomly selected one which runs in free client mode. All clients send
|
// except a randomly selected one which runs in free client mode. All clients send
|
||||||
// similar requests at the maximum allowed rate and the test verifies whether the
|
// similar requests at the maximum allowed rate and the test verifies whether the
|
||||||
// ratio of processed requests is close enough to the ratio of assigned bandwidths.
|
// ratio of processed requests is close enough to the ratio of assigned capacitys.
|
||||||
// Running multiple rounds with different settings ensures that changing bandwidth
|
// Running multiple rounds with different settings ensures that changing capacity
|
||||||
// while connected and going back and forth between free and priority mode with
|
// while connected and going back and forth between free and priority mode with
|
||||||
// the supplied API calls is also thoroughly tested.
|
// the supplied API calls is also thoroughly tested.
|
||||||
func testBandwidthAPI(t *testing.T, clientCount int) {
|
func testCapacityAPI(t *testing.T, clientCount int) {
|
||||||
if testServerDataDir == "" {
|
if testServerDataDir == "" {
|
||||||
// Skip test if no data dir specified
|
// Skip test if no data dir specified
|
||||||
return
|
return
|
||||||
|
|
@ -97,11 +97,11 @@ func testBandwidthAPI(t *testing.T, clientCount int) {
|
||||||
t.Fatalf("Failed to obtain rpc client: %v", err)
|
t.Fatalf("Failed to obtain rpc client: %v", err)
|
||||||
}
|
}
|
||||||
headNum, headHash := getHead(ctx, t, serverRpcClient)
|
headNum, headHash := getHead(ctx, t, serverRpcClient)
|
||||||
totalBw, minBw := bandwidthLimits(ctx, t, serverRpcClient)
|
totalBw, minBw := capacityLimits(ctx, t, serverRpcClient)
|
||||||
fmt.Printf("Server totalBw: %d minBw: %d head number: %d head hash: %064x\n", totalBw, minBw, headNum, headHash)
|
fmt.Printf("Server totalBw: %d minBw: %d head number: %d head hash: %064x\n", totalBw, minBw, headNum, headHash)
|
||||||
reqMinBw := uint64(float64(totalBw) * minRelBw / (minRelBw + float64(len(clients)-1)))
|
reqMinBw := uint64(float64(totalBw) * minRelBw / (minRelBw + float64(len(clients)-1)))
|
||||||
if minBw > reqMinBw {
|
if minBw > reqMinBw {
|
||||||
t.Fatalf("Minimum client bandwidth (%d) bigger than required minimum for this test (%d)", minBw, reqMinBw)
|
t.Fatalf("Minimum client capacity (%d) bigger than required minimum for this test (%d)", minBw, reqMinBw)
|
||||||
}
|
}
|
||||||
|
|
||||||
freeIdx := rand.Intn(len(clients))
|
freeIdx := rand.Intn(len(clients))
|
||||||
|
|
@ -116,7 +116,7 @@ func testBandwidthAPI(t *testing.T, clientCount int) {
|
||||||
|
|
||||||
fmt.Println("connecting client", i)
|
fmt.Println("connecting client", i)
|
||||||
if i != freeIdx {
|
if i != freeIdx {
|
||||||
setBandwidth(ctx, t, serverRpcClient, client.ID(), totalBw/uint64(len(clients)))
|
setCapacity(ctx, t, serverRpcClient, client.ID(), totalBw/uint64(len(clients)))
|
||||||
}
|
}
|
||||||
net.Connect(client.ID(), server.ID())
|
net.Connect(client.ID(), server.ID())
|
||||||
|
|
||||||
|
|
@ -180,7 +180,7 @@ func testBandwidthAPI(t *testing.T, clientCount int) {
|
||||||
|
|
||||||
weights := make([]float64, len(clients))
|
weights := make([]float64, len(clients))
|
||||||
for c := 0; c < 5; c++ {
|
for c := 0; c < 5; c++ {
|
||||||
setBandwidth(ctx, t, serverRpcClient, clients[freeIdx].ID(), freeBw)
|
setCapacity(ctx, t, serverRpcClient, clients[freeIdx].ID(), freeBw)
|
||||||
freeIdx = rand.Intn(len(clients))
|
freeIdx = rand.Intn(len(clients))
|
||||||
var sum float64
|
var sum float64
|
||||||
for i, _ := range clients {
|
for i, _ := range clients {
|
||||||
|
|
@ -193,16 +193,16 @@ func testBandwidthAPI(t *testing.T, clientCount int) {
|
||||||
}
|
}
|
||||||
for i, client := range clients {
|
for i, client := range clients {
|
||||||
weights[i] *= float64(totalBw-freeBw-100) / sum
|
weights[i] *= float64(totalBw-freeBw-100) / sum
|
||||||
bandwidth := uint64(weights[i])
|
capacity := uint64(weights[i])
|
||||||
if i != freeIdx && bandwidth < getBandwidth(ctx, t, serverRpcClient, client.ID()) {
|
if i != freeIdx && capacity < getCapacity(ctx, t, serverRpcClient, client.ID()) {
|
||||||
setBandwidth(ctx, t, serverRpcClient, client.ID(), bandwidth)
|
setCapacity(ctx, t, serverRpcClient, client.ID(), capacity)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
setBandwidth(ctx, t, serverRpcClient, clients[freeIdx].ID(), 0)
|
setCapacity(ctx, t, serverRpcClient, clients[freeIdx].ID(), 0)
|
||||||
for i, client := range clients {
|
for i, client := range clients {
|
||||||
bandwidth := uint64(weights[i])
|
capacity := uint64(weights[i])
|
||||||
if i != freeIdx && bandwidth > getBandwidth(ctx, t, serverRpcClient, client.ID()) {
|
if i != freeIdx && capacity > getCapacity(ctx, t, serverRpcClient, client.ID()) {
|
||||||
setBandwidth(ctx, t, serverRpcClient, client.ID(), bandwidth)
|
setCapacity(ctx, t, serverRpcClient, client.ID(), capacity)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
weights[freeIdx] = float64(freeBw)
|
weights[freeIdx] = float64(freeBw)
|
||||||
|
|
@ -295,39 +295,39 @@ func testRequest(ctx context.Context, t *testing.T, client *rpc.Client) {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
func setBandwidth(ctx context.Context, t *testing.T, server *rpc.Client, clientID enode.ID, bw uint64) {
|
func setCapacity(ctx context.Context, t *testing.T, server *rpc.Client, clientID enode.ID, bw uint64) {
|
||||||
if err := server.CallContext(ctx, nil, "les_setClientBandwidth", clientID, bw); err != nil {
|
if err := server.CallContext(ctx, nil, "les_setClientCapacity", clientID, bw); err != nil {
|
||||||
t.Fatalf("Failed to set client bandwidth: %v", err)
|
t.Fatalf("Failed to set client capacity: %v", err)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
func getBandwidth(ctx context.Context, t *testing.T, server *rpc.Client, clientID enode.ID) uint64 {
|
func getCapacity(ctx context.Context, t *testing.T, server *rpc.Client, clientID enode.ID) uint64 {
|
||||||
var s string
|
var s string
|
||||||
if err := server.CallContext(ctx, &s, "les_getClientBandwidth", clientID); err != nil {
|
if err := server.CallContext(ctx, &s, "les_getClientCapacity", clientID); err != nil {
|
||||||
t.Fatalf("Failed to get client bandwidth: %v", err)
|
t.Fatalf("Failed to get client capacity: %v", err)
|
||||||
}
|
}
|
||||||
bw, err := hexutil.DecodeUint64(s)
|
bw, err := hexutil.DecodeUint64(s)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
t.Fatalf("Failed to decode client bandwidth: %v", err)
|
t.Fatalf("Failed to decode client capacity: %v", err)
|
||||||
}
|
}
|
||||||
return bw
|
return bw
|
||||||
}
|
}
|
||||||
|
|
||||||
func bandwidthLimits(ctx context.Context, t *testing.T, server *rpc.Client) (uint64, uint64) {
|
func capacityLimits(ctx context.Context, t *testing.T, server *rpc.Client) (uint64, uint64) {
|
||||||
var s string
|
var s string
|
||||||
if err := server.CallContext(ctx, &s, "les_totalBandwidth"); err != nil {
|
if err := server.CallContext(ctx, &s, "les_totalCapacity"); err != nil {
|
||||||
t.Fatalf("Failed to query total bandwidth: %v", err)
|
t.Fatalf("Failed to query total capacity: %v", err)
|
||||||
}
|
}
|
||||||
total, err := hexutil.DecodeUint64(s)
|
total, err := hexutil.DecodeUint64(s)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
t.Fatalf("Failed to decode total bandwidth: %v", err)
|
t.Fatalf("Failed to decode total capacity: %v", err)
|
||||||
}
|
}
|
||||||
if err := server.CallContext(ctx, &s, "les_minimumBandwidth"); err != nil {
|
if err := server.CallContext(ctx, &s, "les_minimumCapacity"); err != nil {
|
||||||
t.Fatalf("Failed to query minimum bandwidth: %v", err)
|
t.Fatalf("Failed to query minimum capacity: %v", err)
|
||||||
}
|
}
|
||||||
min, err := hexutil.DecodeUint64(s)
|
min, err := hexutil.DecodeUint64(s)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
t.Fatalf("Failed to decode minimum bandwidth: %v", err)
|
t.Fatalf("Failed to decode minimum capacity: %v", err)
|
||||||
}
|
}
|
||||||
return total, min
|
return total, min
|
||||||
}
|
}
|
||||||
|
|
@ -459,7 +459,7 @@ func newLesClientService(ctx *adapters.ServiceContext) (node.Service, error) {
|
||||||
func newLesServerService(ctx *adapters.ServiceContext) (node.Service, error) {
|
func newLesServerService(ctx *adapters.ServiceContext) (node.Service, error) {
|
||||||
config := eth.DefaultConfig
|
config := eth.DefaultConfig
|
||||||
config.SyncMode = downloader.FullSync
|
config.SyncMode = downloader.FullSync
|
||||||
config.LightServ = testServerBandwidth
|
config.LightServ = testServerCapacity
|
||||||
config.LightPeers = testMaxClients
|
config.LightPeers = testMaxClients
|
||||||
ethereum, err := eth.New(ctx.NodeContext, &config)
|
ethereum, err := eth.New(ctx.NodeContext, &config)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
|
|
@ -30,9 +30,9 @@ const (
|
||||||
// fcTimeConst is the time constant applied for MinRecharge during linear
|
// fcTimeConst is the time constant applied for MinRecharge during linear
|
||||||
// buffer recharge period
|
// buffer recharge period
|
||||||
fcTimeConst = time.Millisecond
|
fcTimeConst = time.Millisecond
|
||||||
// DecParamDelay is applied at server side when decreasing bandwidth in order to
|
// DecParamDelay is applied at server side when decreasing capacity in order to
|
||||||
// avoid a buffer underrun error due to requests sent by the client before
|
// avoid a buffer underrun error due to requests sent by the client before
|
||||||
// receiving the bandwidth update announcement
|
// receiving the capacity update announcement
|
||||||
DecParamDelay = time.Second * 2
|
DecParamDelay = time.Second * 2
|
||||||
// keepLogs is the duration of keeping logs; logging is not used if zero
|
// keepLogs is the duration of keeping logs; logging is not used if zero
|
||||||
keepLogs = 0
|
keepLogs = 0
|
||||||
|
|
@ -40,7 +40,7 @@ const (
|
||||||
|
|
||||||
// ServerParams are the flow control parameters specified by a server for a client
|
// ServerParams are the flow control parameters specified by a server for a client
|
||||||
//
|
//
|
||||||
// Note: a server can assign different amounts of bandwidth to each client by giving
|
// Note: a server can assign different amounts of capacity to each client by giving
|
||||||
// different parameters to them.
|
// different parameters to them.
|
||||||
type ServerParams struct {
|
type ServerParams struct {
|
||||||
BufLimit, MinRecharge uint64
|
BufLimit, MinRecharge uint64
|
||||||
|
|
|
||||||
|
|
@ -45,7 +45,7 @@ type cmNodeFields struct {
|
||||||
// values and perfect precision is required.
|
// values and perfect precision is required.
|
||||||
const FixedPointMultiplier = 1000000
|
const FixedPointMultiplier = 1000000
|
||||||
|
|
||||||
// ClientManager controls the bandwidth assigned to the clients of a server.
|
// ClientManager controls the capacity assigned to the clients of a server.
|
||||||
// Since ServerParams guarantee a safe lower estimate for processable requests
|
// Since ServerParams guarantee a safe lower estimate for processable requests
|
||||||
// even in case of all clients being active, ClientManager calculates a
|
// even in case of all clients being active, ClientManager calculates a
|
||||||
// corrigated buffer value and usually allows a higher remaining buffer value
|
// corrigated buffer value and usually allows a higher remaining buffer value
|
||||||
|
|
|
||||||
|
|
@ -27,7 +27,7 @@ import (
|
||||||
|
|
||||||
type testNode struct {
|
type testNode struct {
|
||||||
node *ClientNode
|
node *ClientNode
|
||||||
bufLimit, bandwidth uint64
|
bufLimit, capacity uint64
|
||||||
waitUntil mclock.AbsTime
|
waitUntil mclock.AbsTime
|
||||||
index, totalCost uint64
|
index, totalCost uint64
|
||||||
}
|
}
|
||||||
|
|
@ -37,35 +37,35 @@ const (
|
||||||
testLength = 100000
|
testLength = 100000
|
||||||
)
|
)
|
||||||
|
|
||||||
// testConstantTotalBandwidth simulates multiple request sender nodes and verifies
|
// testConstantTotalCapacity simulates multiple request sender nodes and verifies
|
||||||
// whether the total amount of served requests matches the expected value based on
|
// whether the total amount of served requests matches the expected value based on
|
||||||
// the total bandwidth and the duration of the test.
|
// the total capacity and the duration of the test.
|
||||||
// Some nodes are sending requests occasionally so that their buffer should regularly
|
// Some nodes are sending requests occasionally so that their buffer should regularly
|
||||||
// reach the maximum while other nodes (the "max capacity nodes") are sending at the
|
// reach the maximum while other nodes (the "max capacity nodes") are sending at the
|
||||||
// maximum permitted rate. The max capacity nodes are changed multiple times during
|
// maximum permitted rate. The max capacity nodes are changed multiple times during
|
||||||
// a single test.
|
// a single test.
|
||||||
func TestConstantTotalBandwidth(t *testing.T) {
|
func TestConstantTotalCapacity(t *testing.T) {
|
||||||
testConstantTotalBandwidth(t, 10, 1, 0)
|
testConstantTotalCapacity(t, 10, 1, 0)
|
||||||
testConstantTotalBandwidth(t, 10, 1, 1)
|
testConstantTotalCapacity(t, 10, 1, 1)
|
||||||
testConstantTotalBandwidth(t, 30, 1, 0)
|
testConstantTotalCapacity(t, 30, 1, 0)
|
||||||
testConstantTotalBandwidth(t, 30, 2, 3)
|
testConstantTotalCapacity(t, 30, 2, 3)
|
||||||
testConstantTotalBandwidth(t, 100, 1, 0)
|
testConstantTotalCapacity(t, 100, 1, 0)
|
||||||
testConstantTotalBandwidth(t, 100, 3, 5)
|
testConstantTotalCapacity(t, 100, 3, 5)
|
||||||
testConstantTotalBandwidth(t, 100, 5, 10)
|
testConstantTotalCapacity(t, 100, 5, 10)
|
||||||
}
|
}
|
||||||
|
|
||||||
func testConstantTotalBandwidth(t *testing.T, nodeCount, maxCapacityNodes, randomSend int) {
|
func testConstantTotalCapacity(t *testing.T, nodeCount, maxCapacityNodes, randomSend int) {
|
||||||
clock := &mclock.Simulated{}
|
clock := &mclock.Simulated{}
|
||||||
nodes := make([]*testNode, nodeCount)
|
nodes := make([]*testNode, nodeCount)
|
||||||
var totalBandwidth uint64
|
var totalCapacity uint64
|
||||||
for i, _ := range nodes {
|
for i, _ := range nodes {
|
||||||
nodes[i] = &testNode{bandwidth: uint64(50000 + rand.Intn(100000))}
|
nodes[i] = &testNode{capacity: uint64(50000 + rand.Intn(100000))}
|
||||||
totalBandwidth += nodes[i].bandwidth
|
totalCapacity += nodes[i].capacity
|
||||||
}
|
}
|
||||||
m := NewClientManager(PieceWiseLinear{{0, totalBandwidth}}, clock)
|
m := NewClientManager(PieceWiseLinear{{0, totalCapacity}}, clock)
|
||||||
for _, n := range nodes {
|
for _, n := range nodes {
|
||||||
n.bufLimit = n.bandwidth * 6000 //uint64(2000+rand.Intn(10000))
|
n.bufLimit = n.capacity * 6000 //uint64(2000+rand.Intn(10000))
|
||||||
n.node = NewClientNode(m, ServerParams{BufLimit: n.bufLimit, MinRecharge: n.bandwidth})
|
n.node = NewClientNode(m, ServerParams{BufLimit: n.bufLimit, MinRecharge: n.capacity})
|
||||||
}
|
}
|
||||||
maxNodes := make([]int, maxCapacityNodes)
|
maxNodes := make([]int, maxCapacityNodes)
|
||||||
for i, _ := range maxNodes {
|
for i, _ := range maxNodes {
|
||||||
|
|
@ -98,9 +98,9 @@ func testConstantTotalBandwidth(t *testing.T, nodeCount, maxCapacityNodes, rando
|
||||||
for _, n := range nodes {
|
for _, n := range nodes {
|
||||||
totalCost += n.totalCost
|
totalCost += n.totalCost
|
||||||
}
|
}
|
||||||
ratio := float64(totalCost) / float64(totalBandwidth) / testLength
|
ratio := float64(totalCost) / float64(totalCapacity) / testLength
|
||||||
if ratio < 0.98 || ratio > 1.02 {
|
if ratio < 0.98 || ratio > 1.02 {
|
||||||
t.Errorf("totalCost/totalBandwidth/testLength ratio incorrect (expected: 1, got: %f)", ratio)
|
t.Errorf("totalCost/totalCapacity/testLength ratio incorrect (expected: 1, got: %f)", ratio)
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
@ -116,9 +116,9 @@ func (n *testNode) send(t *testing.T, now mclock.AbsTime) bool {
|
||||||
rcost := uint64(rand.Int63n(testMaxCost))
|
rcost := uint64(rand.Int63n(testMaxCost))
|
||||||
bv := n.node.RequestProcessed(0, n.index, testMaxCost, rcost)
|
bv := n.node.RequestProcessed(0, n.index, testMaxCost, rcost)
|
||||||
if bv < testMaxCost {
|
if bv < testMaxCost {
|
||||||
n.waitUntil = now + mclock.AbsTime((testMaxCost-bv)*1001000/n.bandwidth)
|
n.waitUntil = now + mclock.AbsTime((testMaxCost-bv)*1001000/n.capacity)
|
||||||
}
|
}
|
||||||
//n.waitUntil = now + mclock.AbsTime(float64(testMaxCost)*1001000/float64(n.bandwidth)*(1-float64(bv)/float64(n.bufLimit)))
|
//n.waitUntil = now + mclock.AbsTime(float64(testMaxCost)*1001000/float64(n.capacity)*(1-float64(bv)/float64(n.bufLimit)))
|
||||||
n.totalCost += rcost
|
n.totalCost += rcost
|
||||||
return true
|
return true
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -197,12 +197,12 @@ func (pm *ProtocolManager) removePeer(id string) {
|
||||||
}
|
}
|
||||||
|
|
||||||
// maxFreePeers returns the maximum number of free client slots based on the number
|
// maxFreePeers returns the maximum number of free client slots based on the number
|
||||||
// and total bandwidth of other clients
|
// and total capacity of other clients
|
||||||
func (pm *ProtocolManager) maxFreePeers(otherPeers int, otherBw uint64) int {
|
func (pm *ProtocolManager) maxFreePeers(otherPeers int, otherBw uint64) int {
|
||||||
if otherPeers >= pm.maxPeers || otherBw >= pm.server.totalBandwidth {
|
if otherPeers >= pm.maxPeers || otherBw >= pm.server.totalCapacity {
|
||||||
return 0
|
return 0
|
||||||
}
|
}
|
||||||
maxPeers := int((pm.server.totalBandwidth - otherBw) / pm.freeClientBw)
|
maxPeers := int((pm.server.totalCapacity - otherBw) / pm.freeClientBw)
|
||||||
if maxPeers <= pm.maxPeers-otherPeers {
|
if maxPeers <= pm.maxPeers-otherPeers {
|
||||||
return maxPeers
|
return maxPeers
|
||||||
}
|
}
|
||||||
|
|
@ -212,9 +212,9 @@ func (pm *ProtocolManager) maxFreePeers(otherPeers int, otherBw uint64) int {
|
||||||
func (pm *ProtocolManager) Start(maxPeers int) {
|
func (pm *ProtocolManager) Start(maxPeers int) {
|
||||||
pm.maxPeers = maxPeers
|
pm.maxPeers = maxPeers
|
||||||
if pm.server != nil && maxPeers > 0 {
|
if pm.server != nil && maxPeers > 0 {
|
||||||
pm.freeClientBw = pm.server.totalBandwidth / uint64(maxPeers)
|
pm.freeClientBw = pm.server.totalCapacity / uint64(maxPeers)
|
||||||
if pm.freeClientBw < pm.server.minBandwidth {
|
if pm.freeClientBw < pm.server.minCapacity {
|
||||||
pm.freeClientBw = pm.server.minBandwidth
|
pm.freeClientBw = pm.server.minCapacity
|
||||||
}
|
}
|
||||||
if pm.freeClientBw > 0 {
|
if pm.freeClientBw > 0 {
|
||||||
pm.server.defParams = flowcontrol.ServerParams{
|
pm.server.defParams = flowcontrol.ServerParams{
|
||||||
|
|
@ -365,7 +365,7 @@ func (pm *ProtocolManager) handle(p *peer) error {
|
||||||
free = false
|
free = false
|
||||||
}
|
}
|
||||||
vip = true
|
vip = true
|
||||||
p.updateBandwidth(bw)
|
p.updateCapacity(bw)
|
||||||
}
|
}
|
||||||
if vip {
|
if vip {
|
||||||
if bw == 0 {
|
if bw == 0 {
|
||||||
|
|
@ -378,10 +378,10 @@ func (pm *ProtocolManager) handle(p *peer) error {
|
||||||
free = true
|
free = true
|
||||||
}
|
}
|
||||||
vip = false
|
vip = false
|
||||||
p.updateBandwidth(pm.freeClientBw)
|
p.updateCapacity(pm.freeClientBw)
|
||||||
} else {
|
} else {
|
||||||
// just update vip bandwidth
|
// just update vip capacity
|
||||||
p.updateBandwidth(bw)
|
p.updateCapacity(bw)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
@ -399,7 +399,7 @@ func (pm *ProtocolManager) handle(p *peer) error {
|
||||||
defer pm.vipClientPool.disconnect(p.ID())
|
defer pm.vipClientPool.disconnect(p.ID())
|
||||||
if vipBw != 0 {
|
if vipBw != 0 {
|
||||||
vip = true
|
vip = true
|
||||||
p.updateBandwidth(vipBw)
|
p.updateCapacity(vipBw)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -43,7 +43,7 @@ var (
|
||||||
|
|
||||||
const maxResponseErrors = 50 // number of invalid responses tolerated (makes the protocol less brittle but still avoids spam)
|
const maxResponseErrors = 50 // number of invalid responses tolerated (makes the protocol less brittle but still avoids spam)
|
||||||
|
|
||||||
// bandwidth limitation for parameter updates
|
// capacity limitation for parameter updates
|
||||||
const (
|
const (
|
||||||
allowedUpdateBytes = 100000 // initial/maximum allowed update size
|
allowedUpdateBytes = 100000 // initial/maximum allowed update size
|
||||||
allowedUpdateRate = time.Millisecond * 10 // time constant for recharging one byte of allowance
|
allowedUpdateRate = time.Millisecond * 10 // time constant for recharging one byte of allowance
|
||||||
|
|
@ -112,7 +112,7 @@ func newPeer(version int, network uint64, isTrusted bool, p *p2p.Peer, rw p2p.Ms
|
||||||
}
|
}
|
||||||
|
|
||||||
// rejectUpdate returns true if a parameter update has to be rejected because
|
// rejectUpdate returns true if a parameter update has to be rejected because
|
||||||
// the size and/or rate of updates exceed the bandwidth limitation
|
// the size and/or rate of updates exceed the capacity limitation
|
||||||
func (p *peer) rejectUpdate(size uint64) bool {
|
func (p *peer) rejectUpdate(size uint64) bool {
|
||||||
now := mclock.Now()
|
now := mclock.Now()
|
||||||
if p.updateCounter == 0 {
|
if p.updateCounter == 0 {
|
||||||
|
|
@ -186,9 +186,9 @@ func (p *peer) waitBefore(maxCost uint64) (time.Duration, float64) {
|
||||||
return p.fcServer.CanSend(maxCost)
|
return p.fcServer.CanSend(maxCost)
|
||||||
}
|
}
|
||||||
|
|
||||||
// updateBandwidth updates the request serving bandwidth assigned to a given client
|
// updateCapacity updates the request serving capacity assigned to a given client
|
||||||
// and also sends an announcement about the updated flow control parameters
|
// and also sends an announcement about the updated flow control parameters
|
||||||
func (p *peer) updateBandwidth(bw uint64) {
|
func (p *peer) updateCapacity(bw uint64) {
|
||||||
p.responseLock.Lock()
|
p.responseLock.Lock()
|
||||||
defer p.responseLock.Unlock()
|
defer p.responseLock.Unlock()
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -54,8 +54,8 @@ type LesServer struct {
|
||||||
quitSync chan struct{}
|
quitSync chan struct{}
|
||||||
onlyAnnounce bool
|
onlyAnnounce bool
|
||||||
|
|
||||||
totalBandwidth, minBandwidth, minBufLimit, bufLimitRatio uint64
|
totalCapacity, minCapacity, minBufLimit, bufLimitRatio uint64
|
||||||
bwcNormal, bwcBlockProcessing flowcontrol.PieceWiseLinear // bandwidth curve for normal operation and block processing mode
|
bwcNormal, bwcBlockProcessing flowcontrol.PieceWiseLinear // capacity curve for normal operation and block processing mode
|
||||||
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
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -107,28 +107,28 @@ func NewLesServer(eth *eth.Ethereum, config *eth.Config) (*LesServer, error) {
|
||||||
bwNormal := uint64(config.LightServ) * flowcontrol.FixedPointMultiplier / 100
|
bwNormal := uint64(config.LightServ) * flowcontrol.FixedPointMultiplier / 100
|
||||||
srv.bwcNormal = flowcontrol.PieceWiseLinear{{0, 0} /*{bwNormal / 10, bwNormal}, */, {bwNormal, bwNormal}}
|
srv.bwcNormal = flowcontrol.PieceWiseLinear{{0, 0} /*{bwNormal / 10, bwNormal}, */, {bwNormal, bwNormal}}
|
||||||
// limit the serving thread count to at least 4 times the targeted average
|
// limit the serving thread count to at least 4 times the targeted average
|
||||||
// bandwidth, allowing more paralellization in short-term load spikes but
|
// capacity, allowing more paralellization in short-term load spikes but
|
||||||
// still limiting the total thread count at a reasonable level
|
// still limiting the total thread count at a reasonable level
|
||||||
srv.thcNormal = int(bwNormal * 4 / flowcontrol.FixedPointMultiplier)
|
srv.thcNormal = int(bwNormal * 4 / flowcontrol.FixedPointMultiplier)
|
||||||
if srv.thcNormal < 4 {
|
if srv.thcNormal < 4 {
|
||||||
srv.thcNormal = 4
|
srv.thcNormal = 4
|
||||||
}
|
}
|
||||||
// while processing blocks use half of the normal target bandwidth
|
// while processing blocks use half of the normal target capacity
|
||||||
bwBlockProcessing := bwNormal / 2
|
bwBlockProcessing := bwNormal / 2
|
||||||
srv.bwcBlockProcessing = flowcontrol.PieceWiseLinear{{0, 0} /*{bwBlockProcessing / 10, bwBlockProcessing}, */, {bwBlockProcessing, bwBlockProcessing}}
|
srv.bwcBlockProcessing = flowcontrol.PieceWiseLinear{{0, 0} /*{bwBlockProcessing / 10, bwBlockProcessing}, */, {bwBlockProcessing, bwBlockProcessing}}
|
||||||
// limit the serving thread count just above the targeted average bandwidth,
|
// limit the serving thread count just above the targeted average capacity,
|
||||||
// ensuring that block processing is minimally hindered
|
// ensuring that block processing is minimally hindered
|
||||||
srv.thcBlockProcessing = int(bwBlockProcessing/flowcontrol.FixedPointMultiplier) + 1
|
srv.thcBlockProcessing = int(bwBlockProcessing/flowcontrol.FixedPointMultiplier) + 1
|
||||||
|
|
||||||
pm.servingQueue.setThreads(srv.thcNormal)
|
pm.servingQueue.setThreads(srv.thcNormal)
|
||||||
srv.fcManager = flowcontrol.NewClientManager(srv.bwcNormal, &mclock.System{})
|
srv.fcManager = flowcontrol.NewClientManager(srv.bwcNormal, &mclock.System{})
|
||||||
|
|
||||||
srv.totalBandwidth = bwNormal
|
srv.totalCapacity = bwNormal
|
||||||
if config.LightBandwidthIn > 0 {
|
if config.LightBandwidthIn > 0 {
|
||||||
pm.inSizeCostFactor = float64(srv.totalBandwidth) / float64(config.LightBandwidthIn)
|
pm.inSizeCostFactor = float64(srv.totalCapacity) / float64(config.LightBandwidthIn)
|
||||||
}
|
}
|
||||||
if config.LightBandwidthOut > 0 {
|
if config.LightBandwidthOut > 0 {
|
||||||
pm.outSizeCostFactor = float64(srv.totalBandwidth) / float64(config.LightBandwidthOut)
|
pm.outSizeCostFactor = float64(srv.totalCapacity) / float64(config.LightBandwidthOut)
|
||||||
}
|
}
|
||||||
srv.fcCostList, srv.minBufLimit = pm.benchmarkCosts(srv.thcNormal, pm.inSizeCostFactor, pm.outSizeCostFactor)
|
srv.fcCostList, srv.minBufLimit = pm.benchmarkCosts(srv.thcNormal, pm.inSizeCostFactor, pm.outSizeCostFactor)
|
||||||
srv.fcCostTable = srv.fcCostList.decode()
|
srv.fcCostTable = srv.fcCostList.decode()
|
||||||
|
|
@ -136,7 +136,7 @@ func NewLesServer(eth *eth.Ethereum, config *eth.Config) (*LesServer, error) {
|
||||||
srv.fcCostStats = newCostStats(srv.fcCostTable)
|
srv.fcCostStats = newCostStats(srv.fcCostTable)
|
||||||
}
|
}
|
||||||
|
|
||||||
srv.minBandwidth = (srv.minBufLimit-1)/bufLimitRatio + 1
|
srv.minCapacity = (srv.minBufLimit-1)/bufLimitRatio + 1
|
||||||
|
|
||||||
chtV1SectionCount, _, _ := srv.chtIndexer.Sections() // indexer still uses LES/1 4k section size for backwards server compatibility
|
chtV1SectionCount, _, _ := srv.chtIndexer.Sections() // indexer still uses LES/1 4k section size for backwards server compatibility
|
||||||
chtV2SectionCount := chtV1SectionCount / (params.CHTFrequencyClient / params.CHTFrequencyServer)
|
chtV2SectionCount := chtV1SectionCount / (params.CHTFrequencyClient / params.CHTFrequencyServer)
|
||||||
|
|
|
||||||
Loading…
Reference in a new issue