Optimize GetFreePort(), bypass string manipulation

net.Listen("tcp", "127.0.0.1:0").Addr is a net.TCPAddr, use a type assertion
to get real value and then we have port.

Seems better, a little bit:

	go test -bench="BenchmarkGetFreePort*" ./util

	goos: linux
	goarch: amd64
	pkg: github.com/smallnest/rpcx/util
	cpu: Intel(R) Core(TM) i7-7500U CPU @ 2.70GHz
	BenchmarkGetFreePort_Old-4        132356              8869 ns/op
	BenchmarkGetFreePort_New-4        139147              8317 ns/op
	PASS
	ok      github.com/smallnest/rpcx/util  2.528s

I notice that GetFreePort() not used in rpcx anymore, is backword compatibility
the reason we must have it?
This commit is contained in:
liaotonglang
2022-01-27 16:43:46 +08:00
parent e543a70ac6
commit 6a14ed3000
2 changed files with 47 additions and 8 deletions

View File

@@ -18,13 +18,7 @@ func GetFreePort() (port int, err error) {
}
defer listener.Close()
addr := listener.Addr().String()
_, portString, err := net.SplitHostPort(addr)
if err != nil {
return 0, err
}
return strconv.Atoi(portString)
return listener.Addr().(*net.TCPAddr).Port, nil
}
// ParseRpcxAddress parses rpcx address such as tcp@127.0.0.1:8972 quic@192.168.1.1:9981

View File

@@ -1,6 +1,51 @@
package util
import "testing"
import (
"net"
"strconv"
"testing"
)
func TestGetFreePort(t *testing.T) {
for i := 0; i < 1000; i++ {
port, err := GetFreePort()
if err != nil {
t.Error(err)
}
if port == 0 {
t.Error("GetFreePort() return 0")
}
}
}
var oldGetFreePort = func() (port int, err error) {
listener, err := net.Listen("tcp", "127.0.0.1:0")
if err != nil {
return 0, err
}
defer listener.Close()
addr := listener.Addr().String()
_, portString, err := net.SplitHostPort(addr)
if err != nil {
return 0, err
}
return strconv.Atoi(portString)
}
func BenchmarkGetFreePort_Old(b *testing.B) {
for i := 0; i < b.N; i++ {
oldGetFreePort()
}
}
func BenchmarkGetFreePort_New(b *testing.B) {
for i := 0; i < b.N; i++ {
GetFreePort()
}
}
func TestExternalIPV4(t *testing.T) {
ip, err := ExternalIPV4()