非反射获取

根据conn类型,将conn断言成相应conn对象,在使用File方法获取file对象,至于为什么是file,参考unix、linux设计哲学:万物皆文件。拿到相应file后直接通过FD方法获取fd句柄。

func getFD(conn net.Conn) int {
	tln := conn.(*net.TCPConn)
	f, err := tln.File()
	if err != nil{
		return  -1
	}
	return int(f.Fd())
}

根据反射获取

func getFDReflect(conn net.Conn) int {
	tcpConn := reflect.Indirect(reflect.ValueOf(conn)).FieldByName("conn")
	fdVal := tcpConn.FieldByName("fd")
	pfdVal := reflect.Indirect(fdVal).FieldByName("pfd")

	return int(pfdVal.FieldByName("Sysfd").Int())
}

两种方式性能比较

  • 非反射
func BenchmarkTest(b *testing.B)  {
	b.ResetTimer()
	for i:=0; i < b.N; i++{
		getFD(conn)
	}
}

// 结果
goos: darwin
goarch: amd64
pkg: github.com/mengboy/1m-go-websockets/4_optimize_gobwas
BenchmarkTest
BenchmarkTest-8   	14268442	        78.5 ns/op
PASS
  • 反射
func BenchmarkReflect(b *testing.B)  {
	b.ResetTimer()
	for i:=0; i < b.N; i++{
		getFDReflect(conn)
	}
}

// 结果
goos: darwin
goarch: amd64
pkg: github.com/mengboy/1m-go-websockets/4_optimize_gobwas
BenchmarkReflect
BenchmarkReflect-8   	 2645677	       457 ns/op
PASS

可以看到反射比起非反射还是性能还是差了几个数量级, 上一篇文章中的fd获取方法可以考虑使用分反射方式。