Reduce allocations in ReverseAddr (#872)

* Add ReverseAddr benchmarks

* Eliminate buffer allocation in ReverseAddr for v6

When the size of a slice is constant it can be allocated on the stack
rather than the heap.

name                old time/op    new time/op    delta
ReverseAddr/IP4-12     175ns ± 5%     173ns ± 4%     ~     (p=0.323 n=10+10)
ReverseAddr/IP6-12     364ns ±14%     218ns ±24%  -40.12%  (p=0.000 n=10+10)

name                old alloc/op   new alloc/op   delta
ReverseAddr/IP4-12     51.0B ± 0%     51.0B ± 0%     ~     (all equal)
ReverseAddr/IP6-12      176B ± 0%       96B ± 0%  -45.45%  (p=0.000 n=10+10)

name                old allocs/op  new allocs/op  delta
ReverseAddr/IP4-12      3.00 ± 0%      3.00 ± 0%     ~     (all equal)
ReverseAddr/IP6-12      3.00 ± 0%      2.00 ± 0%  -33.33%  (p=0.000 n=10+10)

* Reduce allocations in ReverseAddr for v4

name                old time/op    new time/op    delta
ReverseAddr/IP4-12     173ns ± 4%     140ns ±13%  -18.97%  (p=0.000 n=10+10)
ReverseAddr/IP6-12     218ns ±24%     218ns ±22%     ~     (p=0.838 n=10+10)

name                old alloc/op   new alloc/op   delta
ReverseAddr/IP4-12     51.0B ± 0%     48.0B ± 0%   -5.88%  (p=0.000 n=10+10)
ReverseAddr/IP6-12     96.0B ± 0%     96.0B ± 0%     ~     (all equal)

name                old allocs/op  new allocs/op  delta
ReverseAddr/IP4-12      3.00 ± 0%      2.00 ± 0%  -33.33%  (p=0.000 n=10+10)
ReverseAddr/IP6-12      2.00 ± 0%      2.00 ± 0%     ~     (all equal)

* Compare returned address in BenchmarkReverseAddr
This commit is contained in:
Tom Thorogood 2018-12-30 20:58:48 +10:30 committed by Miek Gieben
parent 56516cf4de
commit b0835fab5e
2 changed files with 37 additions and 4 deletions

View File

@ -244,12 +244,19 @@ func ReverseAddr(addr string) (arpa string, err error) {
if ip == nil {
return "", &Error{err: "unrecognized address: " + addr}
}
if ip.To4() != nil {
return strconv.Itoa(int(ip[15])) + "." + strconv.Itoa(int(ip[14])) + "." + strconv.Itoa(int(ip[13])) + "." +
strconv.Itoa(int(ip[12])) + ".in-addr.arpa.", nil
if v4 := ip.To4(); v4 != nil {
buf := make([]byte, 0, net.IPv4len*4+len("in-addr.arpa."))
// Add it, in reverse, to the buffer
for i := len(v4) - 1; i >= 0; i-- {
buf = strconv.AppendInt(buf, int64(v4[i]), 10)
buf = append(buf, '.')
}
// Append "in-addr.arpa." and return (buf already has the final .)
buf = append(buf, "in-addr.arpa."...)
return string(buf), nil
}
// Must be IPv6
buf := make([]byte, 0, len(ip)*4+len("ip6.arpa."))
buf := make([]byte, 0, net.IPv6len*4+len("ip6.arpa."))
// Add it, in reverse, to the buffer
for i := len(ip) - 1; i >= 0; i-- {
v := ip[i]

View File

@ -342,3 +342,29 @@ func BenchmarkIdGeneration(b *testing.B) {
_ = id()
}
}
func BenchmarkReverseAddr(b *testing.B) {
b.Run("IP4", func(b *testing.B) {
for n := 0; n < b.N; n++ {
addr, err := ReverseAddr("192.0.2.1")
if err != nil {
b.Fatal(err)
}
if expect := "1.2.0.192.in-addr.arpa."; addr != expect {
b.Fatalf("invalid reverse address, expected %q, got %q", expect, addr)
}
}
})
b.Run("IP6", func(b *testing.B) {
for n := 0; n < b.N; n++ {
addr, err := ReverseAddr("2001:db8::68")
if err != nil {
b.Fatal(err)
}
if expect := "8.6.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.8.b.d.0.1.0.0.2.ip6.arpa."; addr != expect {
b.Fatalf("invalid reverse address, expected %q, got %q", expect, addr)
}
}
})
}