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:
https://github.com/stevvooe/ttrpc/blob/45d16b41b590938186c5c7cde8088607b3933231/unixcreds.go#L23-L35
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.
What version of Go are you using (
go version)?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:Notice that the benchmark that uses the unix socket credentials is much slower. The code in question is available here:
https://github.com/stevvooe/ttrpc/blob/45d16b41b590938186c5c7cde8088607b3933231/unixcreds.go#L23-L35
After some experimentation, I found that removing the call to
(*UnixConn).Filegot rid of the performance discrepancy. As an experiment, I applied the following patch to thenetpackage to access the fd directly and pass that tounix.GetsockoptUcred:When I ran the benchmark with that change, passing
(*UnixConn).Fddirectly tounix.GetsockoptUcred, without calling(*UnixConn).File, I then got the following benchmark numbers: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.