Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

REUSE_PORT: define in Linux #487

Closed
wants to merge 3 commits into from
Closed

REUSE_PORT: define in Linux #487

wants to merge 3 commits into from

Conversation

miekg
Copy link
Owner

@miekg miekg commented May 1, 2017

Set SO_REUSEADDR on the UDP socket for improved performance.

For some reason syscall.SO_REUSEPORT is not defined for Linux/amd64,386.
Hack around this by taking the value 0x0200 and play with build tags.

Also add code that sets these values on the socket.

I've only locally tested this with an UDP server, don't know if there
are any regression for TCP (or improvements)
@miekg
Copy link
Owner Author

miekg commented May 1, 2017

This came up in coredns/perf-tests#4
cc @andrewtj @asergeyev could you take a look? Thanks!

@miekg
Copy link
Owner Author

miekg commented May 1, 2017

Hmmm, in isolation the test works:

% go test -v -run TestShutdownUDP                                                                                             ~/g/src/github.com/miekg/dns so_reuseport
=== RUN   TestShutdownUDP
--- PASS: TestShutdownUDP (0.00s)
PASS

@miekg
Copy link
Owner Author

miekg commented May 1, 2017

something, something, reuse:

% for i in {0..10}; do go test -v -run TestShutdownUDP; done                                                                  ~/g/src/github.com/miekg/dns so_reuseport
=== RUN   TestShutdownUDP
--- PASS: TestShutdownUDP (0.00s)
PASS
ok  	github.com/miekg/dns	1.012s
=== RUN   TestShutdownUDP
--- PASS: TestShutdownUDP (0.00s)
PASS
ok  	github.com/miekg/dns	1.010s
=== RUN   TestShutdownUDP
--- PASS: TestShutdownUDP (0.00s)
PASS
ok  	github.com/miekg/dns	1.015s
=== RUN   TestShutdownUDP
--- PASS: TestShutdownUDP (0.00s)
PASS
ok  	github.com/miekg/dns	1.011s
=== RUN   TestShutdownUDP
--- PASS: TestShutdownUDP (0.00s)
PASS
ok  	github.com/miekg/dns	1.009s
=== RUN   TestShutdownUDP
--- PASS: TestShutdownUDP (0.00s)
PASS
ok  	github.com/miekg/dns	1.010s
=== RUN   TestShutdownUDP
--- PASS: TestShutdownUDP (0.00s)
PASS
ok  	github.com/miekg/dns	1.010s
=== RUN   TestShutdownUDP
--- PASS: TestShutdownUDP (0.00s)
PASS
ok  	github.com/miekg/dns	1.023s
=== RUN   TestShutdownUDP
--- FAIL: TestShutdownUDP (2.00s)
	server_test.go:573: Could not shutdown test UDP server. Gave up waiting
FAIL
exit status 1
FAIL	github.com/miekg/dns	2.011s
=== RUN   TestShutdownUDP
--- FAIL: TestShutdownUDP (2.00s)
	server_test.go:573: Could not shutdown test UDP server. Gave up waiting
FAIL
exit status 1
FAIL	github.com/miekg/dns	2.017s
=== RUN   TestShutdownUDP
--- FAIL: TestShutdownUDP (2.00s)
	server_test.go:573: Could not shutdown test UDP server. Gave up waiting
FAIL
exit status 1
FAIL	github.com/miekg/dns	2.024s

@miekg
Copy link
Owner Author

miekg commented May 1, 2017

For some weird reason the srv.inFlight sync.WaitGroup is not zero once we reach the Shutdown() code. I have no idea why.

@asergeyev
Copy link
Collaborator

Commenting setting reuse fixes it so somehow they really related....

@asergeyev
Copy link
Collaborator

asergeyev commented May 1, 2017

http://lxr.free-electrons.com/source/include/uapi/asm-generic/socket.h#L25 where did you get constant from?

It's not failing with 15 for me but fails with 0x0200

@miekg
Copy link
Owner Author

miekg commented May 1, 2017

It's not the WaitGroup (doing a inFlight.Done() in Shutdown() crashes with negative value every time).

@miekg
Copy link
Owner Author

miekg commented May 1, 2017

@asergeyev ghe. I got the value from some page I can't find anymore :( Original patch going in kernel I think. Anyway seems to match values in Golang:

 grep -i REUSEPORT *                                                                                                                         ~/upstream/go/src/syscall
net_nacl.go:	SO_REUSEPORT
zerrors_darwin_386.go:	SO_REUSEPORT                      = 0x200
zerrors_darwin_amd64.go:	SO_REUSEPORT                      = 0x200
zerrors_darwin_arm64.go:	SO_REUSEPORT                      = 0x200
zerrors_darwin_arm.go:	SO_REUSEPORT                = 0x200
zerrors_dragonfly_amd64.go:	SO_REUSEPORT                      = 0x200
zerrors_freebsd_386.go:	SO_REUSEPORT                      = 0x200
zerrors_freebsd_amd64.go:	SO_REUSEPORT                      = 0x200
zerrors_freebsd_arm.go:	SO_REUSEPORT                      = 0x200
zerrors_linux_arm64.go:	SO_REUSEPORT                     = 0xf
zerrors_linux_mips64.go:	SO_REUSEPORT                     = 0x200
zerrors_linux_mips64le.go:	SO_REUSEPORT                     = 0x200
zerrors_linux_mips.go:	SO_REUSEPORT                     = 0x200
zerrors_linux_mipsle.go:	SO_REUSEPORT                     = 0x200
zerrors_linux_ppc64.go:	SO_REUSEPORT                     = 0xf
zerrors_linux_ppc64le.go:	SO_REUSEPORT                     = 0xf
zerrors_linux_s390x.go:	SO_REUSEPORT                     = 0xf
zerrors_netbsd_386.go:	SO_REUSEPORT                      = 0x200
zerrors_netbsd_amd64.go:	SO_REUSEPORT                      = 0x200
zerrors_netbsd_arm.go:	SO_REUSEPORT                      = 0x200
zerrors_openbsd_386.go:	SO_REUSEPORT                      = 0x200
zerrors_openbsd_amd64.go:	SO_REUSEPORT                      = 0x200
zerrors_openbsd_arm.go:	SO_REUSEPORT                      = 0x200

@asergeyev
Copy link
Collaborator

asergeyev commented May 1, 2017

#include <sys/socket.h>
#include <stdio.h>

int main() {
    printf("%d\n", SO_REUSEPORT);
}

Prints 15 for me.

See http://lxr.free-electrons.com/ident?i=SO_REUSEPORT risc stuff says 0x200, others set to 15

I don't know what OSX would do.

@miekg
Copy link
Owner Author

miekg commented May 1, 2017

Hmmm. Ghe :) Good be. Then interesting why:
https://gist.github.com/miekg/e80d2eadfea48422178cdbaaf9f8a33f
would speed CoreDNS up. Only the REUSEADDR?

I'll double check. Also try your value. Seems legit.

@miekg
Copy link
Owner Author

miekg commented May 1, 2017

Also, also what does 0x200 do then???

@asergeyev
Copy link
Collaborator

It's not my value, it's what 4.10.9-200.fc25.x86_64 printed for me. I don't know kernel deep enough to know what would happen upon receiving 0x200. I'd expect some error and in case of test C program I actually get ENOPROTOOPT

@asergeyev
Copy link
Collaborator

@miekg
Copy link
Owner Author

miekg commented May 1, 2017

Confused about the figures... Now everything on my machine is fast and I can't reproduce the original case of getting 45K qps :/

Running go test -run='___' -bench BenchmarkServe -v does not indicate any speedup between this and master

@asergeyev
Copy link
Collaborator

BenchmarkServe should not be changed since it's single goroutine that reads from single socket handle.

@miekg
Copy link
Owner Author

miekg commented May 1, 2017

BenchmarkServe should not be changed since it's single goroutine that reads from single socket handle.
Yeah, true. Only matters when we optimize internal code paths.

Thanks for double checking me on this whole thread @asergeyev

@miekg
Copy link
Owner Author

miekg commented May 19, 2017

This doesn't help. Active perf testing of CoreDNS (and thus Go DNS) is happening in github.com/coredns/perf-tests

@miekg miekg closed this May 19, 2017
@miekg miekg deleted the so_reuseport branch June 4, 2017 12:30
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

Successfully merging this pull request may close these issues.

None yet

2 participants