connsock_bench_darwin_test.go 3.5 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115
  1. //go:build !e2e_testing
  2. package udp
  3. import (
  4. "log/slog"
  5. "net"
  6. "net/netip"
  7. "testing"
  8. "time"
  9. )
  10. // benchConnSocks opens a wildcard listener with ListenOut running, with the connected socket knobs pinned to
  11. // their defaults and then cfg applied, and a loopback peer that never reads, so its sends cost only the sender.
  12. func benchConnSocks(b *testing.B, s Settings, cfg func(*connSockConfig)) (*StdConn, netip.AddrPort) {
  13. b.Helper()
  14. for k, v := range map[string]string{
  15. "NEBULA_CONNSOCKS": "8",
  16. "NEBULA_CONNSOCK_RUN": "64",
  17. "NEBULA_CONNSOCK_WINDOW": "1s",
  18. "NEBULA_CONNSOCK_IDLE": "30s",
  19. "NEBULA_CONNSOCK_OPEN_EVERY": "1s",
  20. } {
  21. b.Setenv(k, v)
  22. }
  23. c, err := NewListener(slog.New(slog.DiscardHandler), s)
  24. if err != nil {
  25. b.Fatal(err)
  26. }
  27. b.Cleanup(func() { _ = c.Close() })
  28. u := c.(*StdConn)
  29. if cfg != nil {
  30. cfg(&u.socks.cfg)
  31. }
  32. go func() { _ = u.ListenOut(func(netip.AddrPort, []byte) {}, func() {}) }()
  33. for u.reader.Load() == nil {
  34. time.Sleep(time.Millisecond)
  35. }
  36. pc, err := net.ListenPacket("udp4", "127.0.0.1:0")
  37. if err != nil {
  38. b.Fatal(err)
  39. }
  40. b.Cleanup(func() { _ = pc.Close() })
  41. return u, pc.LocalAddr().(*net.UDPAddr).AddrPort()
  42. }
  43. // BenchmarkConnSockWriteTo measures one WriteTo of a full-size datagram down each path: the listener with
  44. // connected sockets off, to a destination that is no tunnel's remote while another is, to an established peer
  45. // that never gets busy, and on a connected socket.
  46. func BenchmarkConnSockWriteTo(b *testing.B) {
  47. pkt := make([]byte, 1400)
  48. cases := []struct {
  49. name string
  50. cfg func(*connSockConfig)
  51. setup func(b *testing.B, u *StdConn, dst netip.AddrPort)
  52. }{
  53. {name: "listener/off", cfg: func(c *connSockConfig) { c.max = 0 }},
  54. {name: "listener/ineligible", setup: func(b *testing.B, u *StdConn, dst netip.AddrPort) {
  55. u.SetEstablishedPeer(netip.AddrPortFrom(dst.Addr(), dst.Port()+1), true)
  56. }},
  57. {name: "listener/eligible-not-busy", cfg: func(c *connSockConfig) { c.run = 1 << 30 },
  58. setup: func(b *testing.B, u *StdConn, dst netip.AddrPort) { u.SetEstablishedPeer(dst, true) }},
  59. {name: "connected", setup: func(b *testing.B, u *StdConn, dst netip.AddrPort) {
  60. u.SetEstablishedPeer(dst, true)
  61. for range u.socks.cfg.run {
  62. _ = u.WriteTo(pkt, dst)
  63. }
  64. if u.connSockFor(dst) == nil {
  65. b.Fatal("no connected socket")
  66. }
  67. }},
  68. }
  69. for _, c := range cases {
  70. b.Run(c.name, func(b *testing.B) {
  71. u, dst := benchConnSocks(b, Settings{Listen: netip.MustParseAddrPort("0.0.0.0:0")}, c.cfg)
  72. if c.setup != nil {
  73. c.setup(b, u, dst)
  74. }
  75. b.ReportAllocs()
  76. b.ResetTimer()
  77. for range b.N {
  78. _ = u.WriteTo(pkt, dst)
  79. }
  80. })
  81. }
  82. }
  83. // BenchmarkConnSockDispatch measures what WriteTo adds before the listener's sendto, without the syscall: a v4
  84. // listener refuses a v6 destination before sending, with connected sockets off or with another peer established.
  85. func BenchmarkConnSockDispatch(b *testing.B) {
  86. pkt := make([]byte, 1400)
  87. dst := netip.MustParseAddrPort("[::1]:4242")
  88. for _, c := range []struct {
  89. name string
  90. cfg func(*connSockConfig)
  91. establish bool
  92. }{
  93. {name: "off", cfg: func(c *connSockConfig) { c.max = 0 }},
  94. {name: "ineligible", establish: true},
  95. } {
  96. b.Run(c.name, func(b *testing.B) {
  97. u, peer := benchConnSocks(b, Settings{Listen: netip.MustParseAddrPort("127.0.0.1:0"), Multi: true}, c.cfg)
  98. if c.establish {
  99. u.SetEstablishedPeer(peer, true)
  100. }
  101. b.ReportAllocs()
  102. b.ResetTimer()
  103. for range b.N {
  104. if u.WriteTo(pkt, dst) == nil {
  105. b.Fatal("sent a v6 datagram on a v4 listener")
  106. }
  107. }
  108. })
  109. }
  110. }