非反射获取
根据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获取方法可以考虑使用分反射方式。