-
-
Notifications
You must be signed in to change notification settings - Fork 81
Description
The problem
Initial query on a cold cache executes faster than with a warmed one.
Reproduction
Here is the test I've been using
class TestDomain
ROOT_NAMESERVERS = %w[
a.root-servers.net
b.root-servers.net
c.root-servers.net
d.root-servers.net
e.root-servers.net
f.root-servers.net
g.root-servers.net
h.root-servers.net
i.root-servers.net
j.root-servers.net
k.root-servers.net
l.root-servers.net
m.root-servers.net
].freeze
def name
"example.com"
end
def recursive_query(type, ns: ROOT_NAMESERVERS)
return [] unless ns.present?
msg = nil
puts "Time: #{Benchmark.realtime { msg = resolve_query(type, ns: ns, recurse: false, cache: ROOT_NAMESERVERS.intersect?(ns)) }}"
return [] unless msg
# The answer is received.
return msg.answer.map { |rr| rr.rdata_to_string } if msg.answer.present?
# Another layer of intermediaries.
authority = msg.authority.
find_all { |rr| rr.type == Dnsruby::Types.NS }.
map(&:rdata).map(&:to_s).reject(&:blank?)
return [] unless authority.present?
recursive_query(type, ns: authority)
end
private
def resolve_query(type, ns: nil, recurse: true, cache: true)
puts "Caching: #{cache} | NS: #{ns.first}"
resolver = Dnsruby::Resolver.
new(recurse: recurse, do_caching: cache, retry_times: 2)
resolver.nameserver = [ns].flatten.shift
resolver.query(name, type)
end
endI tested this from a Rails console environment, and the numbers look strange:
Loading development environment (Rails 8.0.2)
3.4.2 :001 > Benchmark.realtime { TestDomain.new.recursive_query("NS") }
Caching: true | NS: a.root-servers.net
Time: 0.12582800001837313
Caching: false | NS: l.gtld-servers.net
Time: 0.12042500008828938
Caching: false | NS: a.iana-servers.net
Time: 0.12831000005826354
=> 0.3755820000078529
3.4.2 :002 > Benchmark.realtime { TestDomain.new.recursive_query("NS") }
Caching: true | NS: a.root-servers.net
Time: 0.21918399981223047
Caching: false | NS: l.gtld-servers.net
Time: 0.32541300007142127
Caching: false | NS: a.iana-servers.net
Time: 0.32564599998295307
=> 0.8710799999535084
3.4.2 :003 > Benchmark.realtime { TestDomain.new.recursive_query("NS") }
Caching: true | NS: a.root-servers.net
Time: 0.22562899999320507
Caching: false | NS: l.gtld-servers.net
Time: 0.3200809999834746
Caching: false | NS: a.iana-servers.net
Time: 0.3220410000067204
=> 0.8686989999841899And even if you switch the caching to be always true, it is still kind of slow:
Loading development environment (Rails 8.0.2)
3.4.2 :001 > Benchmark.realtime { TestDomain.new.recursive_query("NS") }
Caching: true | NS: a.root-servers.net
Time: 0.1284089998807758
Caching: true | NS: l.gtld-servers.net
Time: 0.12005099980160594
Caching: true | NS: a.iana-servers.net
Time: 0.12974500004202127
=> 0.37913599982857704
3.4.2 :002 > Benchmark.realtime { TestDomain.new.recursive_query("NS") }
Caching: true | NS: a.root-servers.net
Time: 0.21118599991314113
=> 0.21136899990960956
3.4.2 :003 > Benchmark.realtime { TestDomain.new.recursive_query("NS") }
Caching: true | NS: a.root-servers.net
Time: 0.21160500007681549
=> 0.2118849998805672I saw this once or twice, which seemed like the cache was hit, but in most cases, it doesn't seem to work.
3.4.2 :002 > Benchmark.realtime { TestDomain.new.recursive_query("NS") }
Caching: true | NS: a.root-servers.net
Time: 0.001236999873071909
=> 0.0012920000590384007When the cache is cold, the query executed in 0.12582800001837313, with pre-warmed cache, the same query with do_cache: true took 0.21918399981223047 instead of 0.0012920000590384007 (which I saw when the cache actually hit). This is about 170 times slower than expected with a warmed cache.
The next queries also increased from 0.12042500008828938 to 0.32541300007142127, so also around 0.2 seconds slower. It feels that the existing cache adds around 0.2 seconds to each query, even those with do_cache: true.