Description
What version of Go are you using (go version
)?
$ go version
go version go1.9.2 linux/amd64
Does this issue reproduce with the latest release?
Yes, this is on 1.9.2. I haven't tried master.
What operating system and processor architecture are you using (go env
)?
linux/amd64, Ubuntu 17.04 with 4.10.0-40-generic kernel
What did you do?
I was trying to track down a performance degradation when using unix socket credentials on an abstract socket (bind address starts with a null byte \x00
). The following benchmark shows the discrepancy:
goos: linux
goarch: amd64
pkg: github.com/stevvooe/ttrpc
BenchmarkRoundTrip-8 50000 22078 ns/op 2593 B/op 43 allocs/op
BenchmarkRoundTripUnixSocketCreds-8 10000 141333 ns/op 2593 B/op 43 allocs/op
PASS
ok github.com/stevvooe/ttrpc 3.142s
Notice that the benchmark that uses the unix socket credentials is much slower. The code in question is available here:
After some experimentation, I found that removing the call to (*UnixConn).File
got rid of the performance discrepancy. As an experiment, I applied the following patch to the net
package to access the fd directly and pass that to unix.GetsockoptUcred
:
diff --git a/net/unixsock.go b/net/unixsock.go.fdfix
index 057940a..df44b1b 100644
--- a/net/unixsock.go
+++ b/net/unixsock.go.fdfix
@@ -63,6 +63,10 @@ type UnixConn struct {
conn
}
+func (c *UnixConn) Fd() uintptr {
+ return uintptr(c.conn.fd.pfd.Sysfd)
+}
+
// SyscallConn returns a raw network connection.
// This implements the syscall.Conn interface.
func (c *UnixConn) SyscallConn() (syscall.RawConn, error) {
When I ran the benchmark with that change, passing (*UnixConn).Fd
directly to unix.GetsockoptUcred
, without calling (*UnixConn).File
, I then got the following benchmark numbers:
goos: linux
goarch: amd64
pkg: github.com/stevvooe/ttrpc
BenchmarkRoundTripUnixSocketCreds-8 50000 21897 ns/op 2593 B/op 43 allocs/op
PASS
ok github.com/stevvooe/ttrpc 1.693s
While this probably isn't a great patch, as making that fd available can probably cause problems with the poller, hopefully this demonstrates the issue with call (*UnixConn).File
. If you need a more minimal example, let me know.
What did you expect to see?
I expected no performance degradation when calling (*UnixConn).File
.
What did you see instead?
A performance degradation after calling (*UnixConn).File
.