ttrpc: use syscall.RawConn to access fd over File

Due to a performance drop when calling `(*net.UnixConn).File`, this
change uses the `syscall.RawConn` directly to call `Control` on the
socket. The result is there is no longer a performance penalty to using
unix socket credentials.

The benchmarks after this change are as follows:

```
goos: linux
goarch: amd64
pkg: github.com/stevvooe/ttrpc
BenchmarkRoundTrip-8                  	   50000	     22474 ns/op	    2593 B/op	      43 allocs/op
BenchmarkRoundTripUnixSocketCreds-8   	  100000	     22120 ns/op	    2593 B/op	      43 allocs/op
PASS
ok  	github.com/stevvooe/ttrpc	4.049s
```

Signed-off-by: Stephen J Day <stephen.day@docker.com>
This commit is contained in:
Stephen J Day 2017-12-01 10:00:50 -08:00
parent 45d16b41b5
commit 0fc9ed6ba0
No known key found for this signature in database
GPG Key ID: 67B3DED84EDC823F

View File

@ -20,17 +20,21 @@ func (fn UnixCredentialsFunc) Handshake(ctx context.Context, conn net.Conn) (net
return nil, nil, errors.Wrap(err, "ttrpc.UnixCredentialsFunc: require unix socket")
}
// TODO(stevvooe): Calling (*UnixConn).File causes a 5x performance
// decrease vs just accessing the fd directly. Need to do some more
// troubleshooting to isolate this to Go runtime or kernel.
fp, err := uc.File()
rs, err := uc.SyscallConn()
if err != nil {
return nil, nil, errors.Wrap(err, "ttrpc.UnixCredentialsFunc: failed to get unix file")
return nil, nil, errors.Wrap(err, "ttrpc.UnixCredentialsFunc: (net.UnixConn).SyscallConn failed")
}
var (
ucred *unix.Ucred
ucredErr error
)
if err := rs.Control(func(fd uintptr) {
ucred, ucredErr = unix.GetsockoptUcred(int(fd), unix.SOL_SOCKET, unix.SO_PEERCRED)
}); err != nil {
return nil, nil, errors.Wrapf(err, "ttrpc.UnixCredentialsFunc: (*syscall.RawConn).Control failed")
}
defer fp.Close() // this gets duped and must be closed when this method is complete.
ucred, err := unix.GetsockoptUcred(int(fp.Fd()), unix.SOL_SOCKET, unix.SO_PEERCRED)
if err != nil {
if ucredErr != nil {
return nil, nil, errors.Wrapf(err, "ttrpc.UnixCredentialsFunc: failed to retrieve socket peer credentials")
}