Skip to content

Commit

Permalink
Improve IsFQDN performance (#1453)
Browse files Browse the repository at this point in the history
* Improve IsFQDN performance

While this code may be slightly less clear, it's significantly faster
and this function seems to be a hot path for certain workloads.

name                 old time/op    new time/op    delta
IsFQDN/no_dot-12       5.86ns ± 2%    1.48ns ± 3%  -74.71%  (p=0.000 n=10+10)
IsFQDN/unescaped-12    8.73ns ± 2%    1.57ns ± 1%  -81.98%  (p=0.000 n=9+8)
IsFQDN/escaped-12      27.4ns ± 2%    23.8ns ± 2%  -13.19%  (p=0.000 n=10+10)
FQDN/is_fqdn-12        8.36ns ± 1%    1.80ns ± 2%  -78.50%  (p=0.000 n=9+10)
FQDN/not_fqdn-12       36.8ns ±15%    33.4ns ±12%   -9.25%  (p=0.035 n=10+10)

* Fixup IsFQDN comment
  • Loading branch information
tmthrgd committed Apr 27, 2023
1 parent c454332 commit 4bdf302
Show file tree
Hide file tree
Showing 2 changed files with 59 additions and 7 deletions.
20 changes: 13 additions & 7 deletions defaults.go
Expand Up @@ -272,18 +272,24 @@ func IsMsg(buf []byte) error {

// IsFqdn checks if a domain name is fully qualified.
func IsFqdn(s string) bool {
s2 := strings.TrimSuffix(s, ".")
if s == s2 {
// Check for (and remove) a trailing dot, returning if there isn't one.
if s == "" || s[len(s)-1] != '.' {
return false
}
s = s[:len(s)-1]

i := strings.LastIndexFunc(s2, func(r rune) bool {
// If we don't have an escape sequence before the final dot, we know it's
// fully qualified and can return here.
if s == "" || s[len(s)-1] != '\\' {
return true
}

// Otherwise we have to check if the dot is escaped or not by checking if
// there are an odd or even number of escape sequences before the dot.
i := strings.LastIndexFunc(s, func(r rune) bool {
return r != '\\'
})

// Test whether we have an even number of escape sequences before
// the dot or none.
return (len(s2)-i)%2 != 0
return (len(s)-i)%2 != 0
}

// IsRRset checks if a set of RRs is a valid RRset as defined by RFC 2181.
Expand Down
46 changes: 46 additions & 0 deletions dns_test.go
Expand Up @@ -314,3 +314,49 @@ func TestTKEY(t *testing.T) {
t.Fatalf("unable to parse TKEY string: %s", newError)
}
}

var (
sinkBool bool
sinkString string
)

func BenchmarkIsFQDN(b *testing.B) {
b.Run("no_dot", func(b *testing.B) {
var r bool
for n := 0; n < b.N; n++ {
r = IsFqdn("www.google.com")
}
sinkBool = r
})
b.Run("unescaped", func(b *testing.B) {
var r bool
for n := 0; n < b.N; n++ {
r = IsFqdn("www.google.com.")
}
sinkBool = r
})
b.Run("escaped", func(b *testing.B) {
var r bool
for n := 0; n < b.N; n++ {
r = IsFqdn(`www.google.com\\\\\\\\.`)
}
sinkBool = r
})
}

func BenchmarkFQDN(b *testing.B) {
b.Run("is_fqdn", func(b *testing.B) {
var r string
for n := 0; n < b.N; n++ {
r = Fqdn("www.google.com.")
}
sinkString = r
})
b.Run("not_fqdn", func(b *testing.B) {
var r string
for n := 0; n < b.N; n++ {
r = Fqdn("www.google.com")
}
sinkString = r
})
}

0 comments on commit 4bdf302

Please sign in to comment.