mirror of
https://gitlab.torproject.org/tpo/anti-censorship/pluggable-transports/snowflake.git
synced 2025-10-13 20:11:19 -04:00
Take ownership of buffer in QueuePacketConn QueueIncoming/WriteTo.
This design is easier to misuse, because it allows the caller to modify the contents of the slice after queueing it, but it avoids an extra allocation + memmove per incoming packet. Before: $ go test -bench='Benchmark(QueueIncoming|WriteTo)' -benchtime=2s -benchmem BenchmarkQueueIncoming-4 7001494 342.4 ns/op 1024 B/op 2 allocs/op BenchmarkWriteTo-4 3777459 627 ns/op 1024 B/op 2 allocs/op After: $ go test -bench=BenchmarkWriteTo -benchtime 2s -benchmem BenchmarkQueueIncoming-4 13361600 170.1 ns/op 512 B/op 1 allocs/op BenchmarkWriteTo-4 6702324 373 ns/op 512 B/op 1 allocs/op Despite the benchmark results, the change in QueueIncoming turns out not to have an effect in practice. It appears that the compiler had already been optimizing out the allocation and copy in QueueIncoming. https://gitlab.torproject.org/tpo/anti-censorship/pluggable-transports/snowflake/-/issues/40187 The WriteTo change, on the other hand, in practice reduces the frequency of garbage collection. https://gitlab.torproject.org/tpo/anti-censorship/pluggable-transports/snowflake/-/issues/40199
This commit is contained in:
parent
d4749d2c1d
commit
839d221883
2 changed files with 52 additions and 13 deletions
43
common/turbotunnel/queuepacketconn_test.go
Normal file
43
common/turbotunnel/queuepacketconn_test.go
Normal file
|
@ -0,0 +1,43 @@
|
|||
package turbotunnel
|
||||
|
||||
import (
|
||||
"testing"
|
||||
"time"
|
||||
)
|
||||
|
||||
type emptyAddr struct{}
|
||||
|
||||
func (_ emptyAddr) Network() string { return "empty" }
|
||||
func (_ emptyAddr) String() string { return "empty" }
|
||||
|
||||
// Run with -benchmem to see memory allocations.
|
||||
func BenchmarkQueueIncoming(b *testing.B) {
|
||||
conn := NewQueuePacketConn(emptyAddr{}, 1*time.Hour)
|
||||
defer conn.Close()
|
||||
|
||||
b.ResetTimer()
|
||||
s := 500
|
||||
for i := 0; i < b.N; i++ {
|
||||
// Use a variable for the length to stop the compiler from
|
||||
// optimizing out the allocation.
|
||||
p := make([]byte, s)
|
||||
conn.QueueIncoming(p, emptyAddr{})
|
||||
}
|
||||
b.StopTimer()
|
||||
}
|
||||
|
||||
// BenchmarkWriteTo benchmarks the QueuePacketConn.WriteTo function.
|
||||
func BenchmarkWriteTo(b *testing.B) {
|
||||
conn := NewQueuePacketConn(emptyAddr{}, 1*time.Hour)
|
||||
defer conn.Close()
|
||||
|
||||
b.ResetTimer()
|
||||
s := 500
|
||||
for i := 0; i < b.N; i++ {
|
||||
// Use a variable for the length to stop the compiler from
|
||||
// optimizing out the allocation.
|
||||
p := make([]byte, s)
|
||||
conn.WriteTo(p, emptyAddr{})
|
||||
}
|
||||
b.StopTimer()
|
||||
}
|
Loading…
Add table
Add a link
Reference in a new issue