github.com/gdamore/mangos@v1.4.0/perf/latency.go (about) 1 // Copyright 2018 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 perf provides utilities to measure mangos peformance against 16 // libnanomsg' perf tools. 17 18 package main 19 20 import ( 21 "fmt" 22 "log" 23 "time" 24 25 "nanomsg.org/go-mangos" 26 "nanomsg.org/go-mangos/protocol/pair" 27 "nanomsg.org/go-mangos/transport/all" 28 ) 29 30 // LatencyServer is the server side -- very much equivalent to local_lat in 31 // nanomsg/perf. It does no measurement at all, just sends packets on the wire. 32 func LatencyServer(addr string, msgSize int, roundTrips int) { 33 s, err := pair.NewSocket() 34 if err != nil { 35 log.Fatalf("Failed to make new pair socket: %v", err) 36 } 37 defer s.Close() 38 39 all.AddTransports(s) 40 l, err := s.NewListener(addr, nil) 41 if err != nil { 42 log.Fatalf("Failed to make new listener: %v", err) 43 } 44 45 // TCP no delay, please! 46 l.SetOption(mangos.OptionNoDelay, true) 47 48 // Make sure we linger a bit on close... 49 err = s.SetOption(mangos.OptionLinger, time.Second) 50 if err != nil { 51 log.Fatalf("Failed set Linger: %v", err) 52 } 53 54 err = l.Listen() 55 if err != nil { 56 log.Fatalf("Failed to listen: %v", err) 57 } 58 for i := 0; i != roundTrips; i++ { 59 msg, err := s.RecvMsg() 60 if err != nil { 61 log.Fatalf("Failed to recv: %v", err) 62 } 63 if len(msg.Body) != msgSize { 64 log.Fatalf("Received wrong message size: %d != %d", len(msg.Body), msgSize) 65 } 66 if err = s.SendMsg(msg); err != nil { 67 log.Fatalf("Failed to send: %v", err) 68 } 69 } 70 } 71 72 // LatencyClient is the client side of the latency test. It measures round 73 // trip times, and is the equivalent to nanomsg/perf/remote_lat. 74 func LatencyClient(addr string, msgSize int, roundTrips int) { 75 s, err := pair.NewSocket() 76 if err != nil { 77 log.Fatalf("Failed to make new pair socket: %v", err) 78 } 79 defer s.Close() 80 81 all.AddTransports(s) 82 d, err := s.NewDialer(addr, nil) 83 if err != nil { 84 log.Fatalf("Failed to make new dialer: %v", err) 85 } 86 87 // TCP no delay, please! 88 d.SetOption(mangos.OptionNoDelay, true) 89 90 // Make sure we linger a bit on close... 91 err = s.SetOption(mangos.OptionLinger, time.Second) 92 if err != nil { 93 log.Fatalf("Failed set Linger: %v", err) 94 } 95 96 err = d.Dial() 97 if err != nil { 98 log.Fatalf("Failed to dial: %v", err) 99 } 100 101 // 100 milliseconds to give TCP a chance to establish 102 //time.Sleep(time.Millisecond * 100) 103 msg := mangos.NewMessage(msgSize) 104 msg.Body = msg.Body[0:msgSize] 105 106 start := time.Now() 107 for i := 0; i < roundTrips; i++ { 108 if err = s.SendMsg(msg); err != nil { 109 log.Fatalf("Failed SendMsg: %v", err) 110 } 111 if msg, err = s.RecvMsg(); err != nil { 112 log.Fatalf("Failed RecvMsg: %v", err) 113 } 114 } 115 finish := time.Now() 116 msg.Free() 117 118 total := (finish.Sub(start)) / time.Microsecond 119 lat := float64(total) / float64(roundTrips*2) 120 fmt.Printf("message size: %d [B]\n", msgSize) 121 fmt.Printf("round trip count: %d\n", roundTrips) 122 fmt.Printf("average latency: %.3f [us]\n", lat) 123 }