Avoids some extra work and string concatenation at query time.
benchmark old allocs new allocs delta
BenchmarkGoLookupIP-32 154 150 -2.60%
BenchmarkGoLookupIPNoSuchHost-32 446 442 -0.90%
BenchmarkGoLookupIPWithBrokenNameServer-32 564 568 +0.71%
benchmark old bytes new bytes delta
BenchmarkGoLookupIP-32 10824 10704 -1.11%
BenchmarkGoLookupIPNoSuchHost-32 43140 42992 -0.34%
BenchmarkGoLookupIPWithBrokenNameServer-32 46616 46680 +0.14%
BenchmarkGoLookupIPWithBrokenNameServer's regression appears to be
because it's actually only performing 1 LookupIP call, so the extra
work done parsing the DNS config file doesn't amortize as well as for
BenchmarkGoLookupIP or BenchmarkGoLOokupIPNoSuchHost, which perform
2000+ LookupIP calls per run.
Update #15473.
Change-Id: I98c8072f2f39e2f2ccd6c55e9e9bd309f5ad68f8
Reviewed-on: https://go-review.googlesource.com/22571
Reviewed-by: Brad Fitzpatrick <bradfitz@golang.org>
if rooted {
return []string{name}
}
+
+ hasNdots := count(name, '.') >= conf.ndots
+ name += "."
+
// Build list of search choices.
names := make([]string, 0, 1+len(conf.search))
// If name has enough dots, try unsuffixed first.
- if count(name, '.') >= conf.ndots {
- names = append(names, name+".")
+ if hasNdots {
+ names = append(names, name)
}
// Try suffixes.
for _, suffix := range conf.search {
- suffixed := name + "." + suffix
- if suffixed[len(suffixed)-1] != '.' {
- suffixed += "."
- }
- names = append(names, suffixed)
+ names = append(names, name+suffix)
}
// Try unsuffixed, if not tried first above.
- if count(name, '.') < conf.ndots {
- names = append(names, name+".")
+ if !hasNdots {
+ names = append(names, name)
}
return names
}
type dnsConfig struct {
servers []string // server addresses (in host:port form) to use
- search []string // suffixes to append to local name
+ search []string // rooted suffixes to append to local name
ndots int // number of dots in name to trigger absolute lookup
timeout time.Duration // wait before giving up on a query, including retries
attempts int // lost packets before giving up on server
case "domain": // set search path to just this domain
if len(f) > 1 {
- conf.search = []string{f[1]}
+ conf.search = []string{ensureRooted(f[1])}
}
case "search": // set search path to given servers
conf.search = make([]string, len(f)-1)
for i := 0; i < len(conf.search); i++ {
- conf.search[i] = f[i+1]
+ conf.search[i] = ensureRooted(f[i+1])
}
case "options": // magic options
return nil
}
if i := byteIndex(hn, '.'); i >= 0 && i < len(hn)-1 {
- return []string{hn[i+1:]}
+ return []string{ensureRooted(hn[i+1:])}
}
return nil
}
func hasPrefix(s, prefix string) bool {
return len(s) >= len(prefix) && s[:len(prefix)] == prefix
}
+
+func ensureRooted(s string) string {
+ if len(s) > 0 && s[len(s)-1] == '.' {
+ return s
+ }
+ return s + "."
+}
name: "testdata/resolv.conf",
want: &dnsConfig{
servers: []string{"8.8.8.8:53", "[2001:4860:4860::8888]:53", "[fe80::1%lo0]:53"},
- search: []string{"localdomain"},
+ search: []string{"localdomain."},
ndots: 5,
timeout: 10 * time.Second,
attempts: 3,
name: "testdata/domain-resolv.conf",
want: &dnsConfig{
servers: []string{"8.8.8.8:53"},
- search: []string{"localdomain"},
+ search: []string{"localdomain."},
ndots: 1,
timeout: 5 * time.Second,
attempts: 2,
name: "testdata/search-resolv.conf",
want: &dnsConfig{
servers: []string{"8.8.8.8:53"},
- search: []string{"test", "invalid"},
+ search: []string{"test.", "invalid."},
ndots: 1,
timeout: 5 * time.Second,
attempts: 2,
ndots: 1,
timeout: 5 * time.Second,
attempts: 2,
- search: []string{"domain.local"},
+ search: []string{"domain.local."},
},
},
{
ndots: 1,
timeout: 5 * time.Second,
attempts: 2,
- search: []string{"domain.local"},
+ search: []string{"domain.local."},
}
if !reflect.DeepEqual(conf, want) {
t.Errorf("missing resolv.conf:\ngot: %+v\nwant: %+v", conf, want)
}{
{
name: "host.long.domain.local",
- want: []string{"long.domain.local"},
+ want: []string{"long.domain.local."},
},
{
name: "host.local",
- want: []string{"local"},
+ want: []string{"local."},
},
{
name: "host",