Skip to content

net: calling (*UnixConn).File leads to performance degredation #22953

Closed
@stevvooe

Description

@stevvooe

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.

Metadata

Metadata

Assignees

No one assigned

    Labels

    DocumentationIssues describing a change to documentation.FrozenDueToAgeNeedsFixThe path to resolution is known, but the work has not been done.help wanted

    Type

    No type

    Projects

    No projects

    Milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions