Created
May 25, 2017 15:11
-
-
Save cstockton/78a1371c1c388dfb88c35d1bea8fc211 to your computer and use it in GitHub Desktop.
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
// https://github.com/osrg/gobgp/pull/1334 | |
package t0 | |
import ( | |
"bytes" | |
"fmt" | |
"net" | |
"testing" | |
) | |
func IpToRadixkeyFast(b []byte, max uint8) string { | |
var backing [128]byte | |
buf := backing[:max] | |
for y, i := 8, 0; y <= len(buf); y, i = y+8, i+1 { | |
n, byt, cur := 8, b[i], buf[y-8:y] | |
for byt > 0 { | |
n-- | |
cur[n] = byte('0' + byt&1) | |
byt >>= 1 | |
} | |
} | |
for i := 0; i < len(buf); i++ { | |
if buf[i] == 0 { | |
buf[i] = '0' | |
} | |
} | |
return string(buf) | |
} | |
func IpToRadixkey(b []byte, max uint8) string { | |
var buffer bytes.Buffer | |
for i := 0; i < len(b) && i < int(max); i++ { | |
fmt.Fprintf(&buffer, "%08b", b[i]) | |
} | |
return buffer.String()[:max] | |
} | |
func CidrToRadixkey(cidr string) string { | |
_, n, _ := net.ParseCIDR(cidr) | |
ones, _ := n.Mask.Size() | |
return IpToRadixkey(n.IP, uint8(ones)) | |
} | |
func TestIpToRadixkey(t *testing.T) { | |
for i := byte(0); i < 255; i += 3 { | |
for y := byte(1); y < 128; y *= 2 { | |
ip := net.IPv4(i, i+2, i+3, i-y) | |
for n := uint8(16); n <= 32; n += 2 { | |
exp := CidrToRadixkey(fmt.Sprintf("%v/%d", ip.To4(), n)) | |
got := IpToRadixkey(ip.To4(), n) | |
if exp != got { | |
t.Fatalf(`exp %v; got %v`, exp, got) | |
} | |
} | |
for n := uint8(116); n <= 128; n += 2 { | |
exp := CidrToRadixkey(fmt.Sprintf("::ffff:%v/%d", ip.To16(), n)) | |
got := IpToRadixkey(ip.To16(), n) | |
if exp != got { | |
t.Fatalf(`exp %v; got %v`, exp, got) | |
} | |
} | |
} | |
} | |
} | |
// IPv4Standard-8 2000000 781 ns/op 148 B/op 6 allocs/op | |
// IPv6Standard-8 500000 2980 ns/op 400 B/op 19 allocs/op | |
// IPv4StandardFast-8 10000000 130 ns/op 32 B/op 1 allocs/op | |
// IPv6StandardFast-8 5000000 288 ns/op 128 B/op 1 allocs/op | |
// PASS | |
func BenchmarkIpToRadix(b *testing.B) { | |
const ( | |
ipv4Str = "127.127.127.127" | |
ipv6Str = "2001:0db8:0000:0000:0000:ff00:0042:832" | |
ipv4Exp = "01111111011111110111111101111111" | |
ipv6Exp = "00100000000000010000110110111000000000000000000000000000000000" + | |
"000000000000000000111111110000000000000000010000100000100000110010" | |
) | |
var ( | |
ipv4IP = net.ParseIP(ipv4Str).To4() | |
ipv6IP = net.ParseIP(ipv6Str).To16() | |
) | |
var got string | |
b.Run(`IPv4Standard`, func(b *testing.B) { | |
b.ReportAllocs() | |
b.ResetTimer() | |
for i := 0; i < b.N; i++ { | |
got = IpToRadixkey(ipv4IP, 32) | |
if len(got) != 32 { | |
b.Fatal(`bad len`) | |
} | |
} | |
}) | |
if ipv4Exp != got { | |
b.Fatalf(`exp %v; got %v`, ipv4Exp, got) | |
} | |
b.Run(`IPv6Standard`, func(b *testing.B) { | |
b.ReportAllocs() | |
b.ResetTimer() | |
for i := 0; i < b.N; i++ { | |
got = IpToRadixkey(ipv6IP, 128) | |
if len(got) != 128 { | |
b.Fatal(`bad len`) | |
} | |
} | |
}) | |
if ipv6Exp != got { | |
b.Fatalf(`exp %v; got %v`, ipv6Exp, got) | |
} | |
b.Run(`IPv4StandardFast`, func(b *testing.B) { | |
b.ReportAllocs() | |
b.ResetTimer() | |
for i := 0; i < b.N; i++ { | |
got = IpToRadixkeyFast(ipv4IP, 32) | |
if len(got) != 32 { | |
b.Fatal(`bad len`) | |
} | |
} | |
}) | |
if ipv4Exp != got { | |
b.Fatalf(`exp %v; got %v`, ipv4Exp, got) | |
} | |
b.Run(`IPv6StandardFast`, func(b *testing.B) { | |
b.ReportAllocs() | |
b.ResetTimer() | |
for i := 0; i < b.N; i++ { | |
got = IpToRadixkeyFast(ipv6IP, 128) | |
if len(got) != 128 { | |
b.Fatal(`bad len`) | |
} | |
} | |
}) | |
if ipv6Exp != got { | |
b.Fatalf(`exp %v; got %v`, ipv6Exp, got) | |
} | |
} |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment