github.com/turingchain2020/turingchain@v1.1.21/system/consensus/solo/solo_test.go (about)

     1  // Copyright Turing Corp. 2018 All Rights Reserved.
     2  // Use of this source code is governed by a BSD-style
     3  // license that can be found in the LICENSE file.
     4  
     5  package solo
     6  
     7  import (
     8  	"bytes"
     9  	"context"
    10  	"fmt"
    11  	"io/ioutil"
    12  	"net/http"
    13  	_ "net/http/pprof" //
    14  	"strings"
    15  	"sync"
    16  	"sync/atomic"
    17  	"testing"
    18  	"time"
    19  
    20  	"github.com/turingchain2020/turingchain/common/log/log15"
    21  	"google.golang.org/grpc"
    22  
    23  	"github.com/turingchain2020/turingchain/common"
    24  	log "github.com/turingchain2020/turingchain/common/log"
    25  	"github.com/turingchain2020/turingchain/queue"
    26  	"github.com/turingchain2020/turingchain/rpc/grpcclient"
    27  	"github.com/decred/base58"
    28  	b58 "github.com/mr-tron/base58"
    29  
    30  	"github.com/turingchain2020/turingchain/types"
    31  	"github.com/turingchain2020/turingchain/util"
    32  	"github.com/turingchain2020/turingchain/util/testnode"
    33  	"github.com/stretchr/testify/assert"
    34  
    35  	//加载系统内置store, 不要依赖plugin
    36  	_ "github.com/turingchain2020/turingchain/system/dapp/init"
    37  	_ "github.com/turingchain2020/turingchain/system/mempool/init"
    38  	_ "github.com/turingchain2020/turingchain/system/store/init"
    39  )
    40  
    41  // 执行: go test -cover
    42  func TestSolo(t *testing.T) {
    43  	mock33 := testnode.New("", nil)
    44  	defer mock33.Close()
    45  	cfg := mock33.GetClient().GetConfig()
    46  	txs := util.GenNoneTxs(cfg, mock33.GetGenesisKey(), 10)
    47  	for i := 0; i < len(txs); i++ {
    48  		mock33.GetAPI().SendTx(txs[i])
    49  	}
    50  	mock33.WaitHeight(1)
    51  	txs = util.GenNoneTxs(cfg, mock33.GetGenesisKey(), 10)
    52  	for i := 0; i < len(txs); i++ {
    53  		mock33.GetAPI().SendTx(txs[i])
    54  	}
    55  	mock33.WaitHeight(2)
    56  }
    57  
    58  func BenchmarkSolo(b *testing.B) {
    59  	cfg := testnode.GetDefaultConfig()
    60  	subcfg := cfg.GetSubConfig()
    61  	solocfg, err := types.ModifySubConfig(subcfg.Consensus["solo"], "waitTxMs", 1000)
    62  	assert.Nil(b, err)
    63  	subcfg.Consensus["solo"] = solocfg
    64  	mock33 := testnode.NewWithConfig(cfg, nil)
    65  	defer mock33.Close()
    66  	txs := util.GenCoinsTxs(cfg, mock33.GetGenesisKey(), int64(b.N))
    67  	var last []byte
    68  	var mu sync.Mutex
    69  	b.ResetTimer()
    70  	done := make(chan struct{}, 10)
    71  	for i := 0; i < 10; i++ {
    72  		go func(index int) {
    73  			for n := index; n < b.N; n += 10 {
    74  				reply, err := mock33.GetAPI().SendTx(txs[n])
    75  				if err != nil {
    76  					assert.Nil(b, err)
    77  				}
    78  				mu.Lock()
    79  				last = reply.GetMsg()
    80  				mu.Unlock()
    81  			}
    82  			done <- struct{}{}
    83  		}(i)
    84  	}
    85  	for i := 0; i < 10; i++ {
    86  		<-done
    87  	}
    88  	mock33.WaitTx(last)
    89  }
    90  
    91  var (
    92  	tlog = log15.New("module", "test solo")
    93  )
    94  
    95  //mempool发送交易 10000tx/s
    96  func BenchmarkSendTx(b *testing.B) {
    97  	if testing.Short() {
    98  		b.Skip("skipping in short mode.")
    99  	}
   100  	cfg := testnode.GetDefaultConfig()
   101  	subcfg := cfg.GetSubConfig()
   102  	cfg.GetModuleConfig().Exec.DisableAddrIndex = true
   103  	solocfg, err := types.ModifySubConfig(subcfg.Consensus["solo"], "waitTxMs", 100)
   104  	assert.Nil(b, err)
   105  	solocfg, err = types.ModifySubConfig(solocfg, "benchMode", true)
   106  	assert.Nil(b, err)
   107  	subcfg.Consensus["solo"] = solocfg
   108  	cfg.GetModuleConfig().RPC.JrpcBindAddr = "localhost:9671"
   109  	cfg.GetModuleConfig().RPC.GrpcBindAddr = "localhost:9672"
   110  	mock33 := testnode.NewWithRPC(cfg, nil)
   111  	log.SetLogLevel("error")
   112  	defer mock33.Close()
   113  	priv := mock33.GetGenesisKey()
   114  	b.ResetTimer()
   115  	b.Run("SendTx-Internal", func(b *testing.B) {
   116  		b.RunParallel(func(pb *testing.PB) {
   117  			for pb.Next() {
   118  				tx := util.CreateNoneTxWithTxHeight(cfg, priv, types.LowAllowPackHeight/2)
   119  				mock33.GetAPI().SendTx(tx)
   120  			}
   121  		})
   122  	})
   123  
   124  	b.Run("SendTx-GRPC", func(b *testing.B) {
   125  		gcli, _ := grpcclient.NewMainChainClient(cfg, "localhost:9672")
   126  		b.RunParallel(func(pb *testing.PB) {
   127  			for pb.Next() {
   128  				tx := util.CreateNoneTxWithTxHeight(cfg, priv, types.LowAllowPackHeight/2)
   129  				_, err := gcli.SendTransaction(context.Background(), tx)
   130  				if err != nil {
   131  					tlog.Error("sendtx grpc", "err", err)
   132  				}
   133  			}
   134  		})
   135  	})
   136  
   137  	http.DefaultTransport.(*http.Transport).MaxIdleConnsPerHost = 100
   138  	defer http.DefaultClient.CloseIdleConnections()
   139  	b.Run("SendTx-JSONRPC", func(b *testing.B) {
   140  		b.RunParallel(func(pb *testing.PB) {
   141  			for pb.Next() {
   142  				tx := util.CreateNoneTxWithTxHeight(cfg, priv, types.LowAllowPackHeight/2)
   143  				poststr := fmt.Sprintf(`{"jsonrpc":"2.0","id":2,"method":"Turingchain.SendTransaction","params":[{"data":"%v"}]}`,
   144  					common.ToHex(types.Encode(tx)))
   145  
   146  				resp, _ := http.Post("http://localhost:9671", "application/json", bytes.NewBufferString(poststr))
   147  				ioutil.ReadAll(resp.Body)
   148  				resp.Body.Close()
   149  			}
   150  		})
   151  	})
   152  }
   153  
   154  //测试每10000笔交易打包的并发时间  3500tx/s
   155  func BenchmarkSoloNewBlock(b *testing.B) {
   156  	if testing.Short() {
   157  		b.Skip("skipping in short mode.")
   158  	}
   159  	cfg := testnode.GetDefaultConfig()
   160  	cfg.GetModuleConfig().Exec.DisableAddrIndex = true
   161  	cfg.GetModuleConfig().Mempool.DisableExecCheck = true
   162  	cfg.GetModuleConfig().RPC.GrpcBindAddr = "localhost:9672"
   163  	subcfg := cfg.GetSubConfig()
   164  	solocfg, err := types.ModifySubConfig(subcfg.Consensus["solo"], "waitTxMs", 100)
   165  	assert.Nil(b, err)
   166  	solocfg, err = types.ModifySubConfig(solocfg, "benchMode", true)
   167  	assert.Nil(b, err)
   168  	subcfg.Consensus["solo"] = solocfg
   169  	mock33 := testnode.NewWithRPC(cfg, nil)
   170  	defer mock33.Close()
   171  	start := make(chan struct{})
   172  	//pub := mock33.GetGenesisKey().PubKey().Bytes()
   173  	var height int64
   174  	for i := 0; i < 10; i++ {
   175  		addr, _ := util.Genaddress()
   176  		go func(addr string) {
   177  			start <- struct{}{}
   178  			conn, err := grpc.Dial("localhost:9672", grpc.WithInsecure())
   179  			if err != nil {
   180  				panic(err.Error())
   181  			}
   182  			defer conn.Close()
   183  			gcli := types.NewTuringchainClient(conn)
   184  			for {
   185  				tx := util.CreateNoneTxWithTxHeight(cfg, mock33.GetGenesisKey(), atomic.LoadInt64(&height)+types.LowAllowPackHeight/2)
   186  				//测试去签名情况
   187  				//tx := util.CreateNoneTxWithTxHeight(cfg, nil, 0)
   188  				//tx.Signature = &types.Signature{
   189  				//	Ty: types.SECP256K1,
   190  				//	Pubkey:pub,
   191  				//}
   192  				_, err := gcli.SendTransaction(context.Background(), tx)
   193  				//_, err := mock33.GetAPI().SendTx(tx)
   194  				if err != nil {
   195  					if strings.Contains(err.Error(), "ErrChannelClosed") {
   196  						return
   197  					}
   198  					tlog.Error("sendtx", "err", err.Error())
   199  					time.Sleep(2 * time.Second)
   200  					continue
   201  				}
   202  			}
   203  		}(addr)
   204  		<-start
   205  	}
   206  	b.ResetTimer()
   207  	for i := 0; i < b.N; i++ {
   208  		err := mock33.WaitHeight(int64(i + 1))
   209  		for err != nil {
   210  			b.Log("SoloNewBlock", "waitblkerr", err)
   211  			time.Sleep(time.Second / 10)
   212  			err = mock33.WaitHeight(int64(i + 1))
   213  		}
   214  		atomic.AddInt64(&height, 1)
   215  	}
   216  }
   217  
   218  // 交易签名性能测试  单核4k
   219  func BenchmarkTxSign(b *testing.B) {
   220  	if testing.Short() {
   221  		b.Skip("skipping in short mode.")
   222  	}
   223  	cfg := testnode.GetDefaultConfig()
   224  	txBenchNum := 10000
   225  	_, priv := util.Genaddress()
   226  	txs := util.GenCoinsTxs(cfg, priv, int64(txBenchNum))
   227  
   228  	start := make(chan struct{})
   229  	wait := make(chan struct{})
   230  	result := make(chan interface{}, txBenchNum)
   231  	//控制并发协程数量
   232  	for i := 0; i < 8; i++ {
   233  		go func() {
   234  			wait <- struct{}{}
   235  			index := 0
   236  			<-start
   237  			for {
   238  				//txs[index%txBenchNum].Sign(types.SECP256K1, priv)
   239  				result <- txs[index%txBenchNum].CheckSign()
   240  				index++
   241  			}
   242  		}()
   243  		<-wait
   244  	}
   245  	b.ResetTimer()
   246  	close(start)
   247  	for i := 0; i < b.N; i++ {
   248  		<-result
   249  	}
   250  }
   251  
   252  //消息队列发送性能, 80w /s
   253  func BenchmarkMsgQueue(b *testing.B) {
   254  	if testing.Short() {
   255  		b.Skip("skipping in short mode.")
   256  	}
   257  	cfg := testnode.GetDefaultConfig()
   258  	q := queue.New("channel")
   259  	q.SetConfig(cfg)
   260  	topicNum := 10
   261  	topics := make([]string, topicNum)
   262  	start := make(chan struct{})
   263  	for i := 0; i < topicNum; i++ {
   264  		topics[i] = fmt.Sprintf("bench-%d", i)
   265  		go func(topic string) {
   266  			start <- struct{}{}
   267  			client := q.Client()
   268  			client.Sub(topic)
   269  			for range client.Recv() {
   270  			}
   271  		}(topics[i])
   272  		<-start
   273  	}
   274  	_, priv := util.Genaddress()
   275  	txs := util.GenCoinsTxs(cfg, priv, 1)
   276  	sendCli := q.Client()
   277  	b.ResetTimer()
   278  	b.RunParallel(func(pb *testing.PB) {
   279  		i := 0
   280  		for pb.Next() {
   281  			msg := sendCli.NewMessage(topics[i%topicNum], int64(i), txs[0])
   282  			err := sendCli.Send(msg, false)
   283  			assert.Nil(b, err)
   284  			i++
   285  		}
   286  	})
   287  }
   288  
   289  func BenchmarkTxHash(b *testing.B) {
   290  	if testing.Short() {
   291  		b.Skip("skipping in short mode.")
   292  	}
   293  	cfg := testnode.GetDefaultConfig()
   294  	_, priv := util.Genaddress()
   295  	txs := util.GenCoinsTxs(cfg, priv, 1)
   296  	b.ResetTimer()
   297  	for i := 0; i < b.N; i++ {
   298  		txs[0].Hash()
   299  	}
   300  }
   301  
   302  func BenchmarkEncode(b *testing.B) {
   303  
   304  	if testing.Short() {
   305  		b.Skip("skipping in short mode.")
   306  	}
   307  	cfg := testnode.GetDefaultConfig()
   308  	_, priv := util.Genaddress()
   309  	txs := util.GenCoinsTxs(cfg, priv, 10000)
   310  
   311  	block := &types.Block{}
   312  	block.Txs = txs
   313  	b.ResetTimer()
   314  	for i := 0; i < b.N; i++ {
   315  		types.Encode(block)
   316  	}
   317  }
   318  
   319  func BenchmarkBase58(b *testing.B) {
   320  
   321  	if testing.Short() {
   322  		b.Skip("skipping in short mode.")
   323  	}
   324  	addr := "12qyocayNF7Lv6C9qW4avxs2E7U41fKSfv"
   325  	buf := base58.Decode(addr)
   326  	b.ResetTimer()
   327  	b.Run("decred-base58", func(b *testing.B) {
   328  		for i := 0; i < b.N; i++ {
   329  			base58.Encode(buf)
   330  		}
   331  	})
   332  
   333  	b.Run("mr-tron-base58", func(b *testing.B) {
   334  		for i := 0; i < b.N; i++ {
   335  			b58.Encode(buf)
   336  		}
   337  	})
   338  }