go.nanomsg.org/mangos/v3@v3.4.3-0.20240217232803-46464076f1f5/perf/throughput.go (about)

     1  // Copyright 2019 The Mangos Authors
     2  //
     3  // Licensed under the Apache License, Version 2.0 (the "License");
     4  // you may not use file except in compliance with the License.
     5  // You may obtain a copy of the license at
     6  //
     7  //    http://www.apache.org/licenses/LICENSE-2.0
     8  //
     9  // Unless required by applicable law or agreed to in writing, software
    10  // distributed under the License is distributed on an "AS IS" BASIS,
    11  // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
    12  // See the License for the specific language governing permissions and
    13  // limitations under the License.
    14  
    15  package main
    16  
    17  import (
    18  	"fmt"
    19  	"log"
    20  	"time"
    21  
    22  	"go.nanomsg.org/mangos/v3/protocol/pair"
    23  	"go.nanomsg.org/mangos/v3/transport/all"
    24  )
    25  
    26  // ThroughputServer is the server side -- very much equivalent to local_thr in
    27  // nanomsg/perf.  It does the measurement by counting packets received.
    28  func ThroughputServer(addr string, msgSize int, count int) {
    29  	s, err := pair.NewSocket()
    30  	if err != nil {
    31  		log.Fatalf("Failed to make new pair socket: %v", err)
    32  	}
    33  	defer func() {
    34  		_ = s.Close()
    35  	}()
    36  
    37  	all.AddTransports(s)
    38  	l, err := s.NewListener(addr, nil)
    39  	if err != nil {
    40  		log.Fatalf("Failed to make new listener: %v", err)
    41  	}
    42  
    43  	if err = l.Listen(); err != nil {
    44  		log.Fatalf("Failed to listen: %v", err)
    45  	}
    46  
    47  	msg, err := s.RecvMsg()
    48  	if err != nil {
    49  		log.Fatalf("Failed to receive start message: %v", err)
    50  	}
    51  	msg.Free()
    52  
    53  	start := time.Now()
    54  
    55  	for i := 0; i != count; i++ {
    56  		msg, err := s.RecvMsg()
    57  		if err != nil {
    58  			log.Fatalf("Failed to recv: %v", err)
    59  		}
    60  		if len(msg.Body) != msgSize {
    61  			log.Fatalf("Received wrong message size: %d != %d", len(msg.Body), msgSize)
    62  		}
    63  		// return to cache to avoid GC
    64  		msg.Free()
    65  	}
    66  
    67  	finish := time.Now()
    68  
    69  	delta := finish.Sub(start)
    70  	deltasec := float64(delta) / float64(time.Second)
    71  	msgpersec := float64(count) / deltasec
    72  	mbps := (float64((count)*8*msgSize) / deltasec) / 1000000.0
    73  	fmt.Printf("message size: %d [B]\n", msgSize)
    74  	fmt.Printf("message count: %d\n", count)
    75  	fmt.Printf("throughput: %d [msg/s]\n", uint64(msgpersec))
    76  	fmt.Printf("throughput: %.3f [Mb/s]\n", mbps)
    77  }
    78  
    79  // ThroughputClient is the client side of the latency test.  It simply sends
    80  // the requested number of packets of given size to the server.  It corresponds
    81  // to remote_thr.
    82  func ThroughputClient(addr string, msgSize int, count int) {
    83  	s, err := pair.NewSocket()
    84  	if err != nil {
    85  		log.Fatalf("Failed to make new pair socket: %v", err)
    86  	}
    87  	defer func() {
    88  		_ = s.Close()
    89  	}()
    90  
    91  	all.AddTransports(s)
    92  	d, err := s.NewDialer(addr, nil)
    93  	if err != nil {
    94  		log.Fatalf("Failed to make new dialer: %v", err)
    95  	}
    96  
    97  	err = d.Dial()
    98  	if err != nil {
    99  		log.Fatalf("Failed to dial: %v", err)
   100  	}
   101  
   102  	// 100 milliseconds to give TCP a chance to establish
   103  	time.Sleep(time.Millisecond * 100)
   104  
   105  	body := make([]byte, msgSize)
   106  	for i := 0; i < msgSize; i++ {
   107  		body[i] = 111
   108  	}
   109  
   110  	// send the start message
   111  	_ = s.Send([]byte{})
   112  
   113  	for i := 0; i < count; i++ {
   114  		if err = s.Send(body); err != nil {
   115  			log.Fatalf("Failed SendMsg: %v", err)
   116  		}
   117  	}
   118  }