Skip to content

Instantly share code, notes, and snippets.

@cstockton
Created May 25, 2017 15:11
Show Gist options
  • Save cstockton/78a1371c1c388dfb88c35d1bea8fc211 to your computer and use it in GitHub Desktop.
Save cstockton/78a1371c1c388dfb88c35d1bea8fc211 to your computer and use it in GitHub Desktop.
// 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