benchmark/frame_templates.go (106 lines of code) (raw):

// Copyright (c) 2015 Uber Technologies, Inc. // Permission is hereby granted, free of charge, to any person obtaining a copy // of this software and associated documentation files (the "Software"), to deal // in the Software without restriction, including without limitation the rights // to use, copy, modify, merge, publish, distribute, sublicense, and/or sell // copies of the Software, and to permit persons to whom the Software is // furnished to do so, subject to the following conditions: // // The above copyright notice and this permission notice shall be included in // all copies or substantial portions of the Software. // // THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR // IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, // FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE // AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER // LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, // OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN // THE SOFTWARE. package benchmark import ( "bytes" "encoding/binary" "io" "time" "github.com/uber/tchannel-go" "github.com/uber/tchannel-go/raw" "github.com/uber/tchannel-go/testutils" ) const ( _idOffset = 4 /* size (2) + type (1) + reserved (1) */ _idOffsetEnd = _idOffset + 4 /* length */ ) type frames struct { outgoing [][]byte incoming [][]byte } func (f frames) duplicate() frames { return frames{ outgoing: deepCopyByteSlice(f.outgoing), incoming: deepCopyByteSlice(f.incoming), } } func deepCopyByteSlice(bs [][]byte) [][]byte { newBs := make([][]byte, len(bs)) for i, b := range bs { newBs[i] = make([]byte, len(b)) copy(newBs[i], b) } return newBs } func (f frames) writeInitReq(w io.Writer) error { _, err := w.Write(f.outgoing[0]) return err } func (f frames) writeInitRes(w io.Writer) error { _, err := w.Write(f.incoming[0]) return err } func (f frames) writeCallReq(id uint32, w io.Writer) (int, error) { frames := f.outgoing[1:] return f.writeMulti(id, w, frames) } func (f frames) writeCallRes(id uint32, w io.Writer) (int, error) { frames := f.incoming[1:] return f.writeMulti(id, w, frames) } func (f frames) writeMulti(id uint32, w io.Writer, frames [][]byte) (int, error) { written := 0 for _, f := range frames { binary.BigEndian.PutUint32(f[_idOffset:_idOffsetEnd], id) if _, err := w.Write(f); err != nil { return written, err } written++ } return written, nil } func getRawCallFrames(timeout time.Duration, svcName string, reqSize int) frames { var fs frames modifier := func(fromClient bool, f *tchannel.Frame) *tchannel.Frame { buf := &bytes.Buffer{} if err := f.WriteOut(buf); err != nil { panic(err) } if fromClient { fs.outgoing = append(fs.outgoing, buf.Bytes()) } else { fs.incoming = append(fs.incoming, buf.Bytes()) } return f } withNewServerClient(svcName, func(server, client *tchannel.Channel) { testutils.RegisterEcho(server, nil) relay, err := NewTCPFrameRelay([]string{server.PeerInfo().HostPort}, modifier) if err != nil { panic(err) } defer relay.Close() args := &raw.Args{ Arg2: getRequestBytes(reqSize), Arg3: getRequestBytes(reqSize), } ctx, cancel := tchannel.NewContext(timeout) defer cancel() if _, _, _, err := raw.Call(ctx, client, relay.HostPort(), svcName, "echo", args.Arg2, args.Arg3); err != nil { panic(err) } }) return fs } func withNewServerClient(svcName string, f func(server, client *tchannel.Channel)) { opts := testutils.NewOpts().SetServiceName(svcName) server, err := testutils.NewServerChannel(opts) if err != nil { panic(err) } defer server.Close() client, err := testutils.NewClientChannel(opts) if err != nil { panic(err) } defer client.Close() f(server, client) }