github.com/igggame/nebulas-go@v2.1.0+incompatible/cmd/network/main.go (about)

     1  // Copyright (C) 2018 go-nebulas authors
     2  //
     3  // This file is part of the go-nebulas library.
     4  //
     5  // the go-nebulas library is free software: you can redistribute it and/or modify
     6  // it under the terms of the GNU General Public License as published by
     7  // the Free Software Foundation, either version 3 of the License, or
     8  // (at your option) any later version.
     9  //
    10  // the go-nebulas library is distributed in the hope that it will be useful,
    11  // but WITHOUT ANY WARRANTY; without even the implied warranty of
    12  // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
    13  // GNU General Public License for more details.
    14  //
    15  // You should have received a copy of the GNU General Public License
    16  // along with the go-nebulas library.  If not, see <http://www.gnu.org/licenses/>.
    17  //
    18  
    19  package main
    20  
    21  import (
    22  	"flag"
    23  	"fmt"
    24  	"log"
    25  	"math/rand"
    26  	"os"
    27  	"runtime"
    28  	"runtime/pprof"
    29  	"time"
    30  
    31  	"github.com/libp2p/go-libp2p-interface-conn"
    32  	"github.com/nebulasio/go-nebulas/core"
    33  	"github.com/nebulasio/go-nebulas/metrics"
    34  	"github.com/nebulasio/go-nebulas/neblet"
    35  	"github.com/nebulasio/go-nebulas/net"
    36  	"github.com/nebulasio/go-nebulas/util/byteutils"
    37  	"github.com/nebulasio/go-nebulas/util/logging"
    38  )
    39  
    40  // Message Type
    41  var (
    42  	PingMessage = "ping"
    43  	PongMessage = "pong"
    44  	messageCh   = make(chan net.Message, 4096)
    45  
    46  	cpuprofile      = flag.String("cpuprofile", "", "write cpu profile `file`")
    47  	memprofile      = flag.String("memprofile", "", "write memory profile to `file`")
    48  	packageSize     = flag.Int64("package_size", 0, "package size, default is 0")
    49  	concurrentCount = flag.Int64("concurrent", 0, "concurrent count, default is 0")
    50  	limitCount      = flag.Int64("limit", 0, "limits of sent message, default is 0, no limit")
    51  )
    52  
    53  func main() {
    54  	flag.Parse()
    55  
    56  	if *cpuprofile != "" {
    57  		f, err := os.Create(*cpuprofile)
    58  		if err != nil {
    59  			log.Fatal("could not create CPU profile: ", err)
    60  		}
    61  		if err := pprof.StartCPUProfile(f); err != nil {
    62  			log.Fatal("could not start CPU profile: ", err)
    63  		}
    64  		defer pprof.StopCPUProfile()
    65  	}
    66  
    67  	// fmt.Printf("%v", flag.Args())
    68  	if len(flag.Args()) < 2 {
    69  		help()
    70  		return
    71  	}
    72  
    73  	// when set to false, NodeID check in stream.go should be ignore.
    74  	conn.EncryptConnections = true
    75  
    76  	// rand.
    77  	rand.Seed(time.Now().UnixNano())
    78  
    79  	// mode
    80  	mode := flag.Args()[0]
    81  	configPath := flag.Args()[1]
    82  
    83  	run(mode, configPath, *packageSize, *concurrentCount, *limitCount)
    84  
    85  	fmt.Printf("done...")
    86  
    87  	if *memprofile != "" {
    88  		f, err := os.Create(*memprofile)
    89  		if err != nil {
    90  			log.Fatal("could not create memory profile: ", err)
    91  		}
    92  		runtime.GC() // get up-to-date statistics
    93  		if err := pprof.WriteHeapProfile(f); err != nil {
    94  			log.Fatal("could not write memory profile: ", err)
    95  		}
    96  		f.Close()
    97  	}
    98  }
    99  
   100  func help() {
   101  	fmt.Printf("%s [server|client] [config] [package size]\n", os.Args[0])
   102  	os.Exit(1)
   103  }
   104  
   105  func run(mode, configPath string, packageSize, concurrentMessageCount, totalMessageCount int64) {
   106  	// config.
   107  	config := neblet.LoadConfig(configPath)
   108  
   109  	// init log.
   110  	logging.Init(config.App.LogFile, config.App.LogLevel, config.App.LogAge)
   111  
   112  	core.SetCompatibilityOptions(config.Chain.ChainId)
   113  
   114  	// neblet.
   115  	neblet, _ := neblet.New(config)
   116  	netService, err := net.NewNebService(neblet)
   117  
   118  	if err != nil {
   119  		fmt.Printf("Error: %s", err)
   120  		os.Exit(1)
   121  	}
   122  
   123  	// register dispatcher.
   124  	netService.Register(net.NewSubscriber(netService, messageCh, false, PingMessage, net.MessageWeightZero))
   125  	netService.Register(net.NewSubscriber(netService, messageCh, false, PongMessage, net.MessageWeightZero))
   126  
   127  	// start server.
   128  	netService.Start()
   129  
   130  	// metrics.
   131  	tps := metrics.NewMeter("tps")
   132  	throughput := metrics.NewMeter("throughput")
   133  	latency := metrics.NewHistogramWithUniformSample("latency", 100)
   134  
   135  	sentMessageCount := int64(0)
   136  
   137  	// first trigger.
   138  	if mode == "client" {
   139  		sentMessageCount += concurrentMessageCount
   140  		time.Sleep(10 * time.Second)
   141  		go func() {
   142  			for i := 0; i < int(concurrentMessageCount); i++ {
   143  				netService.SendMessageToPeers(PingMessage, GenerateData(packageSize), net.MessagePriorityNormal, new(net.ChainSyncPeersFilter))
   144  			}
   145  		}()
   146  	}
   147  
   148  	ticker := time.NewTicker(5 * time.Second)
   149  
   150  	for {
   151  		select {
   152  		case message := <-messageCh:
   153  			messageName := message.MessageType()
   154  			switch messageName {
   155  			case PingMessage:
   156  				data := message.Data()
   157  				sendAt := ParseData(data)
   158  				nowAt := time.Now().UnixNano()
   159  
   160  				latencyVal := (nowAt - sendAt) / int64(1000000)
   161  
   162  				// metrics.
   163  				tps.Mark(1)
   164  				throughput.Mark(1 * int64(net.NebMessageHeaderLength+len(data)))
   165  				latency.Update(latencyVal)
   166  
   167  				netService.SendMessageToPeer(PongMessage, message.Data(), net.MessagePriorityNormal, message.MessageFrom())
   168  			case PongMessage:
   169  				data := message.Data()
   170  				sendAt := ParseData(data)
   171  				nowAt := time.Now().UnixNano()
   172  				latencyVal := (nowAt - sendAt) / int64(1000000)
   173  
   174  				// metrics.
   175  				tps.Mark(1)
   176  				throughput.Mark(1 * int64(net.NebMessageHeaderLength+len(data)))
   177  				latency.Update(latencyVal)
   178  
   179  				sentMessageCount++
   180  				if totalMessageCount > 0 && sentMessageCount >= totalMessageCount {
   181  					return
   182  				}
   183  
   184  				netService.SendMessageToPeer(PingMessage, GenerateData(packageSize), net.MessagePriorityNormal, message.MessageFrom())
   185  			}
   186  		case <-ticker.C:
   187  			fmt.Printf("[Perf] tps: %6.2f/s; throughput: %6.2fk/s; latency p95: %6.2f\n", tps.Rate1(), throughput.Rate1()/1000, latency.Percentile(float64(0.50)))
   188  		}
   189  	}
   190  }
   191  
   192  // ParseData parse int64 from bytes
   193  func ParseData(data []byte) int64 {
   194  	return byteutils.Int64(data)
   195  }
   196  
   197  // GenerateData convert int64 into bytes
   198  func GenerateData(packageSize int64) []byte {
   199  	data := make([]byte, 8+packageSize)
   200  	copy(data, byteutils.FromInt64(time.Now().UnixNano()))
   201  	return data
   202  }