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

net: DialTimeout causes persistent slowdown on windows #70751

Open
leemojiang opened this issue Dec 10, 2024 · 4 comments
Open

net: DialTimeout causes persistent slowdown on windows #70751

leemojiang opened this issue Dec 10, 2024 · 4 comments
Labels
NeedsInvestigation Someone must examine and confirm this is a valid issue and not a duplicate of an existing one. OS-Windows

Comments

@leemojiang
Copy link

Go version

go version go1.23.3 windows/amd64

Output of go env in your module/workspace:

set GO111MODULE=
set GOARCH=amd64
set GOBIN=
set GOCACHE=C:\Users\Administrator\AppData\Local\go-build
set GOENV=C:\Users\Administrator\AppData\Roaming\go\env
set GOEXE=.exe
set GOEXPERIMENT=
set GOFLAGS=
set GOHOSTARCH=amd64
set GOHOSTOS=windows
set GOINSECURE=
set GOMODCACHE=C:\Users\Administrator\go\pkg\mod
set GONOPROXY=
set GONOSUMDB=
set GOOS=windows
set GOPATH=C:\Users\Administrator\go
set GOPRIVATE=
set GOPROXY=https://goproxy.cn,direct
set GOROOT=C:\Program Files\Go
set GOSUMDB=sum.golang.org
set GOTMPDIR=
set GOTOOLCHAIN=auto
set GOTOOLDIR=C:\Program Files\Go\pkg\tool\windows_amd64
set GOVCS=
set GOVERSION=go1.23.3
set GODEBUG=
set GOTELEMETRY=local
set GOTELEMETRYDIR=C:\Users\Administrator\AppData\Roaming\go\telemetry
set GCCGO=gccgo
set GOAMD64=v1
set AR=ar
set CC=gcc
set CXX=g++
set CGO_ENABLED=0
set GOMOD=NUL
set GOWORK=
set CGO_CFLAGS=-O2 -g
set CGO_CPPFLAGS=
set CGO_CXXFLAGS=-O2 -g
set CGO_FFLAGS=-O2 -g
set CGO_LDFLAGS=-O2 -g
set PKG_CONFIG=pkg-config
set GOGCCFLAGS=-m64 -fno-caret-diagnostics -Qunused-arguments -Wl,--no-gc-sections -fmessage-length=0 -ffile-prefix-map=C:\Users\ADMINI~1\AppData\Local\Temp\go-build1513341593=/tmp/go-build -gno-record-gcc-switches

What did you do?

I am practicing with a simple port scanner. At first I used net.Dial and the program completes very fast as the following shows:
Normal running time

However when I switch to net.DialTimeout, the program beomes mysteriously slow (30~40 times slower). The side effect seems to be system level, rollback to net.Dial and recompile can't solve the problem. The side effect is gone after a restart.
The program becomes slow
Dial is also slow

I make some test and found out the side effect seems to happen after net.DialTimeout connect a non local address. DialTimeout on 127.0.0.1 is fine, after connecting a nonlocal ip address, the forementioned side effect is triggered. Dialing localhost becomes very slow(both net.Dial and net.DialTimeout ), and the only way to solve it is to restart.
DialTimeout for 127.0.0.1 is fine

Here is the full code:

package main

import (
	"flag"
	"fmt"
	"net"
	"sync"
	"time"
)

var (
	ip      string
	minport int
	maxport int
	timeout int
)

func init() {
	flag.StringVar(&ip, "ip", "127.0.0.1", "Ip to scan.")
	flag.IntVar(&minport, "p1", 0, "Port to scan from.")
	flag.IntVar(&maxport, "p2", 1024, "Port to scan stop.")
	flag.IntVar(&timeout, "t", 1000, "Time out in microseconds")
	flag.Parse()
}

func main() {
	start := time.Now()

	ports := []int{}
	wg := &sync.WaitGroup{}
	mutex := &sync.Mutex{}

	for p := minport; p <= maxport; p++ {
		wg.Add(1)
		go portScan(ip, p, wg, &ports, mutex)
	}

	wg.Wait()

	elasped := time.Since(start)
	fmt.Println("Scanned from ", minport, " to ", maxport, " in ", elasped)
	fmt.Println(ports)
}
func portScan(ip string, port int, wg *sync.WaitGroup, ports *[]int, mutex *sync.Mutex) {
	defer wg.Done()
	address := fmt.Sprintf("%s:%d", ip, port)
	fmt.Println("Connecting ", address)
	conn, err := net.Dial("tcp", address)
	// conn, err := net.DialTimeout("tcp", address, 500*time.Microsecond)

	if err == nil {
		defer conn.Close()
		// fmt.Println("Connection successful.")
		// localAddr := conn.LocalAddr().String()
		// remoteAddr := conn.RemoteAddr().String()
		// fmt.Println("Local Address:", localAddr)
		// fmt.Println("Remote Address:", remoteAddr)

		mutex.Lock()
		*ports = append(*ports, port)
		mutex.Unlock()

	} else {
		// fmt.Println("Error", err)
	}

}

What did you see happen?

As above.

What did you expect to see?

As above.

@seankhliao seankhliao changed the title net:DialTimeout causes mysterious side effects net: DialTimeout causes persistent slowdown on windows Dec 10, 2024
@seankhliao
Copy link
Member

cc @golang/windows

note that your timeout is unreasonably short for any sort of non local connection

@qmuntal
Copy link
Member

qmuntal commented Dec 10, 2024

Thansk for reporting. Can you reproduce the same issue with Go 1.22?

@qmuntal qmuntal added OS-Windows NeedsInvestigation Someone must examine and confirm this is a valid issue and not a duplicate of an existing one. labels Dec 10, 2024
@leemojiang
Copy link
Author

leemojiang commented Dec 11, 2024

cc @golang/windows

note that your timeout is unreasonably short for any sort of non local connection

Thanks. I have tried different time (3 seconds) still got the issue. Once dialed a non local address, the slow down will be triggered.

Thansk for reporting. Can you reproduce the same issue with Go 1.22?

Glad I could help. I conduct some tests on go1.22.10 windows/amd64, the issue is also triggered but act a little diferent:The first time dialing non local address, the program finished in about 20s ( time out set to 3 seconds), while the second time it results in 1m38s. After that even localhost is slowed down.
2nd time dial
3nd time localhost

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
NeedsInvestigation Someone must examine and confirm this is a valid issue and not a duplicate of an existing one. OS-Windows
Projects
None yet
Development

No branches or pull requests

4 participants