Merge pull request #80 from millerkil/optimize

A couple optimizations
This commit is contained in:
Miek Gieben 2014-01-27 23:58:06 -08:00
commit 27abc83e6a
3 changed files with 83 additions and 18 deletions

View File

@ -242,7 +242,8 @@ func TestMsgLenTest(t *testing.T) {
}
}
func BenchmarkMsgLen(b *testing.B) {
// Padded to fix alignment
func BenchmarkMsgLen____(b *testing.B) {
b.StopTimer()
makeMsg := func(question string, ans, ns, e []RR) *Msg {
msg := new(Msg)
@ -263,7 +264,6 @@ func BenchmarkMsgLen(b *testing.B) {
}
func BenchmarkMsgLenPack(b *testing.B) {
b.StopTimer()
makeMsg := func(question string, ans, ns, e []RR) *Msg {
msg := new(Msg)
msg.SetQuestion(Fqdn(question), TypeANY)
@ -276,10 +276,58 @@ func BenchmarkMsgLenPack(b *testing.B) {
name1 := "12345678901234567890123456789012345.12345678.123."
rrMx, _ := NewRR(name1 + " 3600 IN MX 10 " + name1)
msg := makeMsg(name1, []RR{rrMx, rrMx}, nil, nil)
b.StartTimer()
b.ResetTimer()
for i := 0; i < b.N; i++ {
b, _ := msg.Pack()
_ = len(b)
_, _ = msg.Pack()
}
}
func BenchmarkMsgPackBuffer(b *testing.B) {
makeMsg := func(question string, ans, ns, e []RR) *Msg {
msg := new(Msg)
msg.SetQuestion(Fqdn(question), TypeANY)
msg.Answer = append(msg.Answer, ans...)
msg.Ns = append(msg.Ns, ns...)
msg.Extra = append(msg.Extra, e...)
msg.Compress = true
return msg
}
name1 := "12345678901234567890123456789012345.12345678.123."
rrMx, _ := NewRR(name1 + " 3600 IN MX 10 " + name1)
msg := makeMsg(name1, []RR{rrMx, rrMx}, nil, nil)
buf := make([]byte, 512)
b.ResetTimer()
for i := 0; i < b.N; i++ {
_, _ = msg.PackBuffer(buf)
}
}
func BenchmarkMsgUnpack(b *testing.B) {
makeMsg := func(question string, ans, ns, e []RR) *Msg {
msg := new(Msg)
msg.SetQuestion(Fqdn(question), TypeANY)
msg.Answer = append(msg.Answer, ans...)
msg.Ns = append(msg.Ns, ns...)
msg.Extra = append(msg.Extra, e...)
msg.Compress = true
return msg
}
name1 := "12345678901234567890123456789012345.12345678.123."
rrMx, _ := NewRR(name1 + " 3600 IN MX 10 " + name1)
msg := makeMsg(name1, []RR{rrMx, rrMx}, nil, nil)
msg_buf, _ := msg.Pack()
b.ResetTimer()
for i := 0; i < b.N; i++ {
_ = msg.Unpack(msg_buf)
}
}
func BenchmarkPackDomainName(b *testing.B) {
name1 := "12345678901234567890123456789012345.12345678.123."
buf := make([]byte, len(name1)+1)
b.ResetTimer()
for i := 0; i < b.N; i++ {
_, _ = PackDomainName(name1, buf, 0, nil, false)
}
}

38
msg.go
View File

@ -254,7 +254,16 @@ func packDomainName(s string, msg []byte, off int, compression map[string]int, c
pointer := -1
// Emit sequence of counted strings, chopping at dots.
begin := 0
bs := []byte(s)
// We can share the message buffer because we don't need to look back.
// Keeping close makes tests more sensitive to failure (only 1 byte of room).
var bs []byte
if len(s) < len(msg) {
bs = msg[off+1:]
copy(bs, s)
} else {
bs = []byte(s)
}
ro_bs, bs_fresh := s, true
for i := 0; i < ls; i++ {
if bs[i] == '\\' {
for j := i; j < ls-1; j++ {
@ -274,6 +283,7 @@ func packDomainName(s string, msg []byte, off int, compression map[string]int, c
}
ls -= 2
}
bs_fresh = false
continue
}
@ -304,12 +314,16 @@ func packDomainName(s string, msg []byte, off int, compression map[string]int, c
}
off++
}
if compress && !bs_fresh {
ro_bs = string(bs)
bs_fresh = true
}
// Dont try to compress '.'
if compression != nil && string(bs[begin:]) != "." {
if p, ok := compression[string(bs[begin:])]; !ok {
if compress && ro_bs[begin:] != "." {
if p, ok := compression[ro_bs[begin:]]; !ok {
// Only offsets smaller than this can be used.
if offset < maxCompressionOffset {
compression[string(bs[begin:])] = offset
compression[ro_bs[begin:]] = offset
}
} else {
// The first hit is the longest matching dname
@ -435,17 +449,19 @@ Loop:
// slices and other (often anonymous) structs.
func packStructValue(val reflect.Value, msg []byte, off int, compression map[string]int, compress bool) (off1 int, err error) {
lenmsg := len(msg)
for i := 0; i < val.NumField(); i++ {
if val.Type().Field(i).Tag == `dns:"-"` {
numfield := val.NumField()
for i := 0; i < numfield; i++ {
typefield := val.Type().Field(i)
if typefield.Tag == `dns:"-"` {
continue
}
switch fv := val.Field(i); fv.Kind() {
default:
return lenmsg, &Error{err: "bad kind packing"}
case reflect.Slice:
switch val.Type().Field(i).Tag {
switch typefield.Tag {
default:
return lenmsg, &Error{"bad tag packing slice: " + val.Type().Field(i).Tag.Get("dns")}
return lenmsg, &Error{"bad tag packing slice: " + typefield.Tag.Get("dns")}
case `dns:"domain-name"`:
for j := 0; j < val.Field(i).Len(); j++ {
element := val.Field(i).Index(j).String()
@ -614,7 +630,7 @@ func packStructValue(val reflect.Value, msg []byte, off int, compression map[str
msg[off+3] = byte(i)
off += 4
case reflect.Uint64:
switch val.Type().Field(i).Tag {
switch typefield.Tag {
default:
if off+8 > lenmsg {
return lenmsg, &Error{err: "overflow packing uint64"}
@ -647,9 +663,9 @@ func packStructValue(val reflect.Value, msg []byte, off int, compression map[str
// There are multiple string encodings.
// The tag distinguishes ordinary strings from domain names.
s := fv.String()
switch val.Type().Field(i).Tag {
switch typefield.Tag {
default:
return lenmsg, &Error{"bad tag packing string: " + val.Type().Field(i).Tag.Get("dns")}
return lenmsg, &Error{"bad tag packing string: " + typefield.Tag.Get("dns")}
case `dns:"base64"`:
b64, e := packBase64([]byte(s))
if e != nil {

View File

@ -65,7 +65,8 @@ func TestServing(t *testing.T) {
}
}
func BenchmarkServing(b *testing.B) {
// Padded to fix alignment
func BenchmarkServe____(b *testing.B) {
b.StopTimer()
HandleFunc("miek.nl.", HelloServer)
a := runtime.GOMAXPROCS(4)
@ -92,7 +93,7 @@ func HelloServerCompress(w ResponseWriter, req *Msg) {
w.WriteMsg(m)
}
func BenchmarkServingCompress(b *testing.B) {
func BenchmarkServeCompress(b *testing.B) {
b.StopTimer()
HandleFunc("miek.nl.", HelloServerCompress)
a := runtime.GOMAXPROCS(4)