Reduce allocations in UnpackDomainName by better sizing slice (#844)
* Reduce allocations in UnpackDomainName by better sizing slice The maximum size of a domain name in presentation format is bounded by the maximum length of a name in wire octet form and the maximum length of a label. As s doesn't escape from UnpackDomainName, we can safely give it the maximum capacity and it will never need to grow. * Benchmark UnpackDomainName with lonest names possible * Rename BenchmarkUnpackDomainNameLongestEscaped to match * Improve maxDomainNamePresentationLength comment * Further improve maxDomainNamePresentationLength comment
This commit is contained in:
parent
b1bf6f1b9b
commit
c0747f060e
|
@ -128,6 +128,36 @@ func BenchmarkUnpackDomainNameUnprintable(b *testing.B) {
|
|||
}
|
||||
}
|
||||
|
||||
func BenchmarkUnpackDomainNameLongest(b *testing.B) {
|
||||
buf := make([]byte, len(longestDomain)+1)
|
||||
n, err := PackDomainName(longestDomain, buf, 0, nil, false)
|
||||
if err != nil {
|
||||
b.Fatal(err)
|
||||
}
|
||||
if n != maxDomainNameWireOctets {
|
||||
b.Fatalf("name wrong size in wire format, expected %d, got %d", maxDomainNameWireOctets, n)
|
||||
}
|
||||
b.ResetTimer()
|
||||
for i := 0; i < b.N; i++ {
|
||||
_, _, _ = UnpackDomainName(buf, 0)
|
||||
}
|
||||
}
|
||||
|
||||
func BenchmarkUnpackDomainNameLongestUnprintable(b *testing.B) {
|
||||
buf := make([]byte, len(longestUnprintableDomain)+1)
|
||||
n, err := PackDomainName(longestUnprintableDomain, buf, 0, nil, false)
|
||||
if err != nil {
|
||||
b.Fatal(err)
|
||||
}
|
||||
if n != maxDomainNameWireOctets {
|
||||
b.Fatalf("name wrong size in wire format, expected %d, got %d", maxDomainNameWireOctets, n)
|
||||
}
|
||||
b.ResetTimer()
|
||||
for i := 0; i < b.N; i++ {
|
||||
_, _, _ = UnpackDomainName(buf, 0)
|
||||
}
|
||||
}
|
||||
|
||||
func BenchmarkCopy(b *testing.B) {
|
||||
b.ReportAllocs()
|
||||
m := new(Msg)
|
||||
|
|
12
msg.go
12
msg.go
|
@ -36,6 +36,16 @@ const (
|
|||
// not something a well written implementation should ever do, so we leave them
|
||||
// to trip the maximum compression pointer check.
|
||||
maxCompressionPointers = (maxDomainNameWireOctets+1)/2 - 2
|
||||
|
||||
// This is the maximum length of a domain name in presentation format. The
|
||||
// maximum wire length of a domain name is 255 octets (see above), with the
|
||||
// maximum label length being 63. The wire format requires one extra byte over
|
||||
// the presentation format, reducing the number of octets by 1. Each label in
|
||||
// the name will be separated by a single period, with each octet in the label
|
||||
// expanding to at most 4 bytes (\DDD). If all other labels are of the maximum
|
||||
// length, then the final label can only be 61 octets long to not exceed the
|
||||
// maximum allowed wire length.
|
||||
maxDomainNamePresentationLength = 61*4 + 1 + 63*4 + 1 + 63*4 + 1 + 63*4 + 1
|
||||
)
|
||||
|
||||
// Errors defined in this package.
|
||||
|
@ -372,7 +382,7 @@ func isRootLabel(s string, bs []byte, off, end int) bool {
|
|||
// When an error is encountered, the unpacked name will be discarded
|
||||
// and len(msg) will be returned as the offset.
|
||||
func UnpackDomainName(msg []byte, off int) (string, int, error) {
|
||||
s := make([]byte, 0, 64)
|
||||
s := make([]byte, 0, maxDomainNamePresentationLength)
|
||||
off1 := 0
|
||||
lenmsg := len(msg)
|
||||
budget := maxDomainNameWireOctets
|
||||
|
|
|
@ -13,6 +13,7 @@ const maxPrintableLabel = "abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ0
|
|||
var (
|
||||
longDomain = maxPrintableLabel[:53] + strings.TrimSuffix(
|
||||
strings.Join([]string{".", ".", ".", ".", "."}, maxPrintableLabel[:49]), ".")
|
||||
|
||||
reChar = regexp.MustCompile(`.`)
|
||||
i = -1
|
||||
maxUnprintableLabel = reChar.ReplaceAllStringFunc(maxPrintableLabel, func(ch string) string {
|
||||
|
@ -21,6 +22,10 @@ var (
|
|||
}
|
||||
return fmt.Sprintf("\\%03d", i)
|
||||
})
|
||||
|
||||
// These are the longest possible domain names in presentation format.
|
||||
longestDomain = maxPrintableLabel[:61] + strings.Join([]string{".", ".", ".", "."}, maxPrintableLabel)
|
||||
longestUnprintableDomain = maxUnprintableLabel[:61*4] + strings.Join([]string{".", ".", ".", "."}, maxUnprintableLabel)
|
||||
)
|
||||
|
||||
func TestPackNoSideEffect(t *testing.T) {
|
||||
|
|
Loading…
Reference in New Issue