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

x/net: Performance degradation on Windows 64 bit when using "tcp4"/"tcp6" as network instead of "tcp" in net.Listen() #40243

Open
ikandaswamy opened this issue Jul 16, 2020 · 4 comments

Comments

@ikandaswamy
Copy link

@ikandaswamy ikandaswamy commented Jul 16, 2020

What version of Go are you using (go version)?

$ go version
1.13.7

Does this issue reproduce with the latest release?

Yes

What operating system and processor architecture are you using (go env)?

Windows 64 bit

go env Output
$ go env

What did you do?

Pre issue we created a single listener for http and use that to Listen with protocol = tcp

listener    net.Listener
func (this *HttpEndpoint) Listen() error {
	ln, err := net.Listen("tcp", this.httpAddr)
	if err == nil {
		this.listener = ln
		srv := &http.Server{
			Handler:           this.mux,
			ReadHeaderTimeout: 5 * time.Second,
		}
		go srv.Serve(ln)
		logging.Infop("HttpEndpoint: Listen", logging.Pair{"Address", ln.Addr()})
	}
	return err
}

Then we changed the code to use tcp4 and/or tcp6 explicitly in the Listen function. The code for this is given below.

  1. If server sends us ipv6=true, then we should
    (1) start listening to ipv6 - fail service if listen fails
    (2) try to listen to ipv4 - don't fail service even if listen fails.
  2. If server sends us ipv6=false, then we should
    (1) start listening to ipv4 - fail service if listen fails
    (2) try to listen to ipv6 - don't fail service even if listen fails.

Create 2 listeners - one for http and one for https.
Code to create the listeners -

listener      []net.Listener

func getNetwProtocol() []string {
	if server.IsIPv6() {
		return []string{"tcp6", "tcp4"}
	}
	return []string{"tcp4", "tcp6"}
}

func (this *HttpEndpoint) Listen() error {

	srv := &http.Server{
		Handler:           this.mux,
		ReadHeaderTimeout: 5 * time.Second,
	}

	for i, netW := range getNetwProtocol() {
		ln, err := net.Listen(netW, this.httpAddr)

		if err != nil {
			if i == 0 {
				return fmt.Errorf("Failed to start service: %v", err.Error())
			} else {
				logging.Infof("Failed to start service: %v", err.Error())
			}
		} else {
			this.listener = append(this.listener, ln)
			go srv.Serve(ln)
			logging.Infop("HttpEndpoint: Listen", logging.Pair{"Address", ln.Addr()})
		}
	}

	return nil
}

What did you expect to see?

No change in performance tests (this is true for the Linux - Centos7 machine and Mac)
Previous throughput - 131K

What did you see instead?

Slowdown only on the Windows performance tests. The throughput on Linux and Mac more or less stayed the same.
On windows we saw a 50% degradation.

I changed the code to test just using tcp and tcp4/tcp6 with the rest of the code being the same. Thats when I see the degradation in performance.

Question - Why is there an performance issue with using tcp4/tcp6 instead of tcp in net.Listen() on Windows ? Is this an expected issue ?

@toothrot toothrot changed the title Performance degradation on Windows 64 bit when using "tcp4"/"tcp6" as network instead of "tcp" in net.Listen() x/net: Performance degradation on Windows 64 bit when using "tcp4"/"tcp6" as network instead of "tcp" in net.Listen() Jul 21, 2020
@gopherbot gopherbot added this to the Unreleased milestone Jul 21, 2020
@toothrot toothrot modified the milestones: Unreleased, Backlog Jul 21, 2020
@toothrot
Copy link
Contributor

@toothrot toothrot commented Jul 21, 2020

@networkimprov
Copy link

@networkimprov networkimprov commented Jul 21, 2020

@bradfitz
Copy link
Contributor

@bradfitz bradfitz commented Jul 21, 2020

Do you have a self-contained minimal repro?

Does this also happen with Go 1.14 or Go 1.15?

@ikandaswamy
Copy link
Author

@ikandaswamy ikandaswamy commented Nov 17, 2020

I tried building with 1.15.4 but I run into a build issue - mingw32/bin/ld.exe: Error: export ordinal too large: 80134 - #40795

But I see the same numbers with go 1.14.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Projects
None yet
Linked pull requests

Successfully merging a pull request may close this issue.

None yet
5 participants