// NewSocket allocates a new Socket. The Socket is the handle used to // access the underlying library. func NewSocket(d Domain, p Protocol) (*Socket, error) { var s Socket var err error s.proto = p s.dom = d switch p { case PUB: s.sock, err = pub.NewSocket() case SUB: s.sock, err = sub.NewSocket() case PUSH: s.sock, err = push.NewSocket() case PULL: s.sock, err = pull.NewSocket() case REQ: s.sock, err = req.NewSocket() case REP: s.sock, err = rep.NewSocket() case SURVEYOR: s.sock, err = surveyor.NewSocket() case RESPONDENT: s.sock, err = respondent.NewSocket() case PAIR: s.sock, err = pair.NewSocket() case BUS: s.sock, err = bus.NewSocket() default: err = mangos.ErrBadProto } if err != nil { return nil, err } switch d { case AF_SP: case AF_SP_RAW: err = s.sock.SetOption(mangos.OptionRaw, true) default: err = errBadDomain } if err != nil { s.sock.Close() return nil, err } // Compat mode sockets should timeout on send if we don't have any pipes if err = s.sock.SetOption(mangos.OptionWriteQLen, 0); err != nil { s.sock.Close() return nil, err } s.rto = -1 s.sto = -1 all.AddTransports(s.sock) return &s, nil }
// ThroughputServer is the server side -- very much equivalent to local_thr in // nanomsg/perf. It does the measurement by counting packets received. func ThroughputServer(addr string, msgSize int, count int) { s, err := pair.NewSocket() if err != nil { log.Fatalf("Failed to make new pair socket: %v", err) } defer s.Close() all.AddTransports(s) l, err := s.NewListener(addr, nil) if err != nil { log.Fatalf("Failed to make new listener: %v", err) } // Disable TCP no delay, please! - only valid for TCP l.SetOption(mangos.OptionNoDelay, false) // Make sure we linger a bit on close... err = s.SetOption(mangos.OptionLinger, time.Second) if err != nil { log.Fatalf("Failed set Linger: %v", err) } err = l.Listen() if err != nil { log.Fatalf("Failed to listen: %v", err) } msg, err := s.RecvMsg() msg.Free() start := time.Now() for i := 0; i != count; i++ { msg, err := s.RecvMsg() if err != nil { log.Fatalf("Failed to recv: %v", err) } if len(msg.Body) != msgSize { log.Fatalf("Received wrong message size: %d != %d", len(msg.Body), msgSize) } // return to cache to avoid GC msg.Free() } finish := time.Now() delta := finish.Sub(start) deltasec := float64(delta) / float64(time.Second) msgpersec := float64(count) / deltasec mbps := (float64((count)*8*msgSize) / deltasec) / 1000000.0 fmt.Printf("message size: %d [B]\n", msgSize) fmt.Printf("message count: %d\n", count) fmt.Printf("throughput: %d [msg/s]\n", uint64(msgpersec)) fmt.Printf("throughput: %.3f [Mb/s]\n", mbps) }
func setSocket(f func() (mangos.Socket, error)) error { var err error if sock != nil { return errors.New("protocol already selected") } sock, err = f() if err != nil { return err } all.AddTransports(sock) return nil }
// LatencyClient is the client side of the latency test. It measures round // trip times, and is the equivalent to nanomsg/perf/remote_lat. func LatencyClient(addr string, msgSize int, roundTrips int) { s, err := pair.NewSocket() if err != nil { log.Fatalf("Failed to make new pair socket: %v", err) } defer s.Close() all.AddTransports(s) d, err := s.NewDialer(addr, nil) if err != nil { log.Fatalf("Failed to make new dialer: %v", err) } // TCP no delay, please! d.SetOption(mangos.OptionNoDelay, true) // Make sure we linger a bit on close... err = s.SetOption(mangos.OptionLinger, time.Second) if err != nil { log.Fatalf("Failed set Linger: %v", err) } err = d.Dial() if err != nil { log.Fatalf("Failed to dial: %v", err) } // 100 milliseconds to give TCP a chance to establish //time.Sleep(time.Millisecond * 100) msg := mangos.NewMessage(msgSize) msg.Body = msg.Body[0:msgSize] start := time.Now() for i := 0; i < roundTrips; i++ { if err = s.SendMsg(msg); err != nil { log.Fatalf("Failed SendMsg: %v", err) } if msg, err = s.RecvMsg(); err != nil { log.Fatalf("Failed RecvMsg: %v", err) } } finish := time.Now() msg.Free() total := (finish.Sub(start)) / time.Microsecond lat := float64(total) / float64(roundTrips*2) fmt.Printf("message size: %d [B]\n", msgSize) fmt.Printf("round trip count: %d\n", roundTrips) fmt.Printf("average latency: %.3f [us]\n", lat) }
func (c *T) Init(t *testing.T, addr string) bool { // Initial defaults c.Lock() defer c.Unlock() c.t = t c.addr = addr c.numrx = 0 // Reset c.numtx = 0 // Reset c.sdoneq = make(chan struct{}) c.rdoneq = make(chan struct{}) c.readyq = make(chan struct{}) c.timeout = time.Second * 3 c.txdelay = time.Duration(time.Now().UnixNano()) % time.Millisecond all.AddTransports(c.Sock) return true }
// ThroughputClient is the client side of the latency test. It simply sends // the requested number of packets of given size to the server. It corresponds // to remote_thr. func ThroughputClient(addr string, msgSize int, count int) { s, err := pair.NewSocket() if err != nil { log.Fatalf("Failed to make new pair socket: %v", err) } defer s.Close() all.AddTransports(s) d, err := s.NewDialer(addr, nil) if err != nil { log.Fatalf("Failed to make new dialer: %v", err) } // Disable TCP no delay, please! d.SetOption(mangos.OptionNoDelay, false) // Make sure we linger a bit on close... err = s.SetOption(mangos.OptionLinger, time.Second) if err != nil { log.Fatalf("Failed set Linger: %v", err) } err = d.Dial() if err != nil { log.Fatalf("Failed to dial: %v", err) } // 100 milliseconds to give TCP a chance to establish time.Sleep(time.Millisecond * 100) body := make([]byte, msgSize) for i := 0; i < msgSize; i++ { body[i] = 111 } // send the start message s.Send([]byte{}) for i := 0; i < count; i++ { if err = s.Send(body); err != nil { log.Fatalf("Failed SendMsg: %v", err) } } }
// LatencyServer is the server side -- very much equivalent to local_lat in // nanomsg/perf. It does no measurement at all, just sends packets on the wire. func LatencyServer(addr string, msgSize int, roundTrips int) { s, err := pair.NewSocket() if err != nil { log.Fatalf("Failed to make new pair socket: %v", err) } defer s.Close() all.AddTransports(s) l, err := s.NewListener(addr, nil) if err != nil { log.Fatalf("Failed to make new listener: %v", err) } // TCP no delay, please! l.SetOption(mangos.OptionNoDelay, true) // Make sure we linger a bit on close... err = s.SetOption(mangos.OptionLinger, time.Second) if err != nil { log.Fatalf("Failed set Linger: %v", err) } err = l.Listen() if err != nil { log.Fatalf("Failed to listen: %v", err) } for i := 0; i != roundTrips; i++ { msg, err := s.RecvMsg() if err != nil { log.Fatalf("Failed to recv: %v", err) } if len(msg.Body) != msgSize { log.Fatalf("Received wrong message size: %d != %d", len(msg.Body), msgSize) } if err = s.SendMsg(msg); err != nil { log.Fatalf("Failed to send: %v", err) } } }
func benchmarkReq(t *testing.B, url string, size int) { if strings.HasPrefix(url, "ipc://") && runtime.GOOS == "windows" { t.Skip("IPC not supported on Windows") return } srvopts := make(map[string]interface{}) cliopts := make(map[string]interface{}) if strings.HasPrefix(url, "wss://") || strings.HasPrefix(url, "tls+tcp://") { srvopts[mangos.OptionTLSConfig] = srvCfg cliopts[mangos.OptionTLSConfig] = cliCfg } srvrdy := make(chan struct{}) srvsock, err := rep.NewSocket() if err != nil || srvsock == nil { t.Errorf("Failed creating server socket: %v", err) return } defer srvsock.Close() all.AddTransports(srvsock) clisock, err := req.NewSocket() if err != nil || clisock == nil { t.Errorf("Failed creating client socket: %v", err) return } defer clisock.Close() all.AddTransports(clisock) go func() { var err error var msg *mangos.Message if err = srvsock.ListenOptions(url, srvopts); err != nil { t.Errorf("Server listen failed: %v", err) return } close(srvrdy) // echo server for { if msg, err = srvsock.RecvMsg(); err != nil { return } if err = srvsock.SendMsg(msg); err != nil { t.Errorf("Server send failed: %v", err) return } } }() if err = clisock.DialOptions(url, cliopts); err != nil { t.Errorf("Client dial failed: %v", err) return } <-srvrdy time.Sleep(time.Millisecond * 1000) t.ResetTimer() msg := make([]byte, size) for i := 0; i < t.N; i++ { if err = clisock.Send(msg); err != nil { t.Errorf("Client send failed: %v", err) return } if msg, err = clisock.Recv(); err != nil { t.Errorf("Client receive failed: %v", err) return } } if size > 128 { t.SetBytes(int64(size)) } t.StopTimer() }
func benchmarkPair(t *testing.B, url string, size int) { if strings.HasPrefix(url, "ipc://") && runtime.GOOS == "windows" { t.Skip("IPC not supported on Windows") return } srvopts := make(map[string]interface{}) cliopts := make(map[string]interface{}) if strings.HasPrefix(url, "wss://") || strings.HasPrefix(url, "tls+tcp://") { srvopts[mangos.OptionTLSConfig] = srvCfg cliopts[mangos.OptionTLSConfig] = cliCfg } finish := make(chan struct{}) ready := make(chan struct{}) srvsock, err := pair.NewSocket() if err != nil || srvsock == nil { t.Errorf("Failed creating server socket: %v", err) return } all.AddTransports(srvsock) defer srvsock.Close() clisock, err := pair.NewSocket() if err != nil || clisock == nil { t.Errorf("Failed creating client socket: %v", err) return } all.AddTransports(clisock) defer clisock.Close() go func() { var err error var m *mangos.Message if err = srvsock.ListenOptions(url, srvopts); err != nil { t.Errorf("Server listen failed: %v", err) return } close(ready) for i := 0; i < t.N; i++ { if m, err = srvsock.RecvMsg(); err != nil { t.Errorf("Error receiving %d: %v", i, err) return } m.Free() } close(finish) }() <-ready if err = clisock.DialOptions(url, cliopts); err != nil { t.Errorf("Client dial failed: %v", err) return } time.Sleep(700 * time.Millisecond) t.ResetTimer() for i := 0; i < t.N; i++ { msg := mangos.NewMessage(size) if err = clisock.SendMsg(msg); err != nil { t.Errorf("Client send failed: %v", err) return } } <-finish t.StopTimer() if size > 128 { t.SetBytes(int64(size)) } }