From 036fb02814ed44086ffe6ae51ec0b8528226ceb2 Mon Sep 17 00:00:00 2001 From: Sanaz Taheri <35961250+staheri14@users.noreply.github.com> Date: Mon, 29 Jan 2024 14:56:43 -0800 Subject: [PATCH] test: channel ID impact on max bandwidth utilization in MConnection (#1189) This PR implements a benchmark test to evaluate how channel IDs influence maximum bandwidth utilization. Part of #1162 --- p2p/conn/connection_bench_test.go | 99 +++++++++++++++++++++++++++++++ 1 file changed, 99 insertions(+) diff --git a/p2p/conn/connection_bench_test.go b/p2p/conn/connection_bench_test.go index 323a3c8e5c..b0255842d8 100644 --- a/p2p/conn/connection_bench_test.go +++ b/p2p/conn/connection_bench_test.go @@ -467,3 +467,102 @@ func BenchmarkMConnection_ScalingPayloadSizes_LowSendRate(b *testing.B) { runBenchmarkTest(b, tt) } } + +// BenchmarkMConnection_Multiple_ChannelID assesses the max bw/send rate +// utilization of MConnection when configured with multiple channel IDs. +func BenchmarkMConnection_Multiple_ChannelID(b *testing.B) { + // These tests create two connections with two channels each, one channel having higher priority. + // Traffic is sent from the client to the server, split between the channels with varying proportions in each test case. + // All tests should complete in 2 seconds (calculated as totalTraffic* msgSize / sendRate), + // demonstrating that channel count doesn't affect max bandwidth utilization. + totalTraffic := 100 + msgSize := 1 * kibibyte + sendRate := 50 * kibibyte + recRate := 50 * kibibyte + chDescs := []*ChannelDescriptor{ + {ID: 0x01, Priority: 1, SendQueueCapacity: 50}, + {ID: 0x02, Priority: 2, SendQueueCapacity: 50}, + } + type testCase struct { + name string + trafficMap map[byte]int // channel ID -> number of messages to be sent + } + var tests []testCase + for i := 0.0; i < 1; i += 0.1 { + tests = append(tests, testCase{ + name: fmt.Sprintf("2 channel IDs with traffic proportion %f %f", + i, 1-i), + trafficMap: map[byte]int{ // channel ID -> number of messages to be sent + 0x01: int(i * float64(totalTraffic)), + 0x02: totalTraffic - int(i*float64(totalTraffic)), // the rest of the traffic + }, + }) + } + for _, tt := range tests { + b.Run(tt.name, func(b *testing.B) { + for n := 0; n < b.N; n++ { + // set up two networked connections + // server, client := NetPipe() // can alternatively use this and comment out the line below + server, client := tcpNetPipe() + defer server.Close() + defer client.Close() + + // prepare callback to receive messages + allReceived := make(chan bool) + receivedLoad := 0 // number of messages received + onReceive := func(chID byte, msgBytes []byte) { + receivedLoad++ + if receivedLoad >= totalTraffic { + allReceived <- true + } + } + + cnfg := DefaultMConnConfig() + cnfg.SendRate = int64(sendRate) + cnfg.RecvRate = int64(recRate) + + // mount the channel descriptors to the connections + clientMconn := NewMConnectionWithConfig(client, chDescs, + func(chID byte, msgBytes []byte) {}, + func(r interface{}) {}, + cnfg) + serverMconn := NewMConnectionWithConfig(server, chDescs, + onReceive, + func(r interface{}) {}, + cnfg) + clientMconn.SetLogger(log.TestingLogger()) + serverMconn.SetLogger(log.TestingLogger()) + + err := clientMconn.Start() + require.Nil(b, err) + defer func() { + _ = clientMconn.Stop() + }() + err = serverMconn.Start() + require.Nil(b, err) + defer func() { + _ = serverMconn.Stop() + }() + + // start measuring the time from here to exclude the time + // taken to set up the connections + b.StartTimer() + // start generating messages over the two channels, + // concurrently, with the specified proportions + for chID, trafficPortion := range tt.trafficMap { + go generateAndSendMessages(clientMconn, + time.Millisecond, + 1*time.Minute, + trafficPortion, + msgSize, + nil, + chID) + } + + // wait for all messages to be received + <-allReceived + b.StopTimer() + } + }) + } +}