From e04f9941d37283b8c7e654c3c8146f73e0f904ae Mon Sep 17 00:00:00 2001 From: bee Date: Thu, 1 Oct 2026 18:54:05 +0100 Subject: [PATCH 1/4] Initialize the fallback DNS resolver only when needed --- src/address.rs | 93 ++++++++++++++++++++++++++++++++++++++++++++------ 1 file changed, 82 insertions(+), 11 deletions(-) diff --git a/src/address.rs b/src/address.rs index df074355..8a43a7f1 100644 --- a/src/address.rs +++ b/src/address.rs @@ -1,4 +1,5 @@ //! Provides functions to parse input IP addresses, CIDRs or files. +use std::cell::LazyCell; use std::collections::BTreeSet; use std::fs::{self, File}; use std::io::{prelude::*, BufReader}; @@ -39,12 +40,23 @@ use crate::warning; /// start your runtime (as the `rustscan` binary does) or from /// `tokio::task::spawn_blocking`, not directly from async code. pub fn parse_addresses(input: &Opts) -> Vec { + parse_addresses_with_resolver(input, || get_resolver(&input.resolver)) +} + +fn parse_addresses_with_resolver( + input: &Opts, + create_resolver: impl FnOnce() -> Resolver, +) -> Vec { let mut ips: Vec = Vec::new(); let mut unresolved_addresses: Vec<&str> = Vec::new(); - let backup_resolver = get_resolver(&input.resolver); + // Most scans use literal IPs or CIDRs. Defer the resolver's runtime and + // hosts-file loading until a DNS fallback actually needs them, then reuse + // that resolver for the rest of the targets and exclusions. + let backup_resolver = LazyCell::new(create_resolver); + let resolver = || &*backup_resolver; for address in &input.addresses { - let parsed_ips = parse_address(address, &backup_resolver); + let parsed_ips = parse_address_with_resolver(address, &resolver); if !parsed_ips.is_empty() { ips.extend(parsed_ips); } else { @@ -66,7 +78,7 @@ pub fn parse_addresses(input: &Opts) -> Vec { continue; } - if let Ok(x) = read_ips_from_file(file_path, &backup_resolver) { + if let Ok(x) = read_ips_from_file(file_path, &resolver) { ips.extend(x); } else { warning!( @@ -77,7 +89,7 @@ pub fn parse_addresses(input: &Opts) -> Vec { } } - let excluded_cidrs = parse_excluded_networks(&input.exclude_addresses, &backup_resolver); + let excluded_cidrs = parse_excluded_networks_with_resolver(&input.exclude_addresses, &resolver); // Remove duplicated/excluded IPs. let mut seen = BTreeSet::new(); @@ -100,6 +112,13 @@ pub fn parse_addresses(input: &Opts) -> Vec { /// let ips = parse_address("127.0.0.1", &Resolver::default().unwrap()); /// ``` pub fn parse_address(address: &str, resolver: &Resolver) -> Vec { + parse_address_with_resolver(address, &|| resolver) +} + +fn parse_address_with_resolver<'a>( + address: &str, + resolver: &impl Fn() -> &'a Resolver, +) -> Vec { if let Ok(addr) = IpAddr::from_str(address) { // `address` is an IP string vec![addr] @@ -118,14 +137,17 @@ pub fn parse_address(address: &str, resolver: &Resolver) -> Vec { } /// Uses DNS to get the IPS associated with host -fn resolve_ips_from_host(source: &str, backup_resolver: &Resolver) -> Vec { +fn resolve_ips_from_host<'a>( + source: &str, + backup_resolver: &impl Fn() -> &'a Resolver, +) -> Vec { let mut ips: Vec = Vec::new(); if let Ok(addrs) = source.to_socket_addrs() { for ip in addrs { ips.push(ip.ip()); } - } else if let Ok(addrs) = backup_resolver.lookup_ip(source) { + } else if let Ok(addrs) = backup_resolver().lookup_ip(source) { ips.extend(addrs.iter()); } @@ -148,6 +170,13 @@ fn resolve_ips_from_host(source: &str, backup_resolver: &Resolver) -> Vec>, resolver: &Resolver, +) -> Vec { + parse_excluded_networks_with_resolver(exclude_addresses, &|| resolver) +} + +fn parse_excluded_networks_with_resolver<'a>( + exclude_addresses: &Option>, + resolver: &impl Fn() -> &'a Resolver, ) -> Vec { exclude_addresses .iter() @@ -157,7 +186,10 @@ pub fn parse_excluded_networks( } /// Parses a single address into an IpCidr, handling CIDR notation, IP addresses, and hostnames. -fn parse_single_excluded_address(addr: &str, resolver: &Resolver) -> Vec { +fn parse_single_excluded_address<'a>( + addr: &str, + resolver: &impl Fn() -> &'a Resolver, +) -> Vec { if let Ok(cidr) = IpCidr::from_str(addr) { return vec![cidr]; } @@ -261,9 +293,9 @@ fn read_resolver_from_file(path: &str) -> Result, std::io::Error> { #[cfg(not(tarpaulin_include))] /// Parses an input file of IPs and uses those -fn read_ips_from_file( +fn read_ips_from_file<'a>( ips: &std::path::Path, - backup_resolver: &Resolver, + backup_resolver: &impl Fn() -> &'a Resolver, ) -> Result, std::io::Error> { let file = File::open(ips)?; let reader = BufReader::new(file); @@ -272,7 +304,7 @@ fn read_ips_from_file( for address_line in reader.lines() { if let Ok(address) = address_line { - ips.extend(parse_address(&address, backup_resolver)); + ips.extend(parse_address_with_resolver(&address, backup_resolver)); } else { debug!("Line in file is not valid"); } @@ -283,9 +315,48 @@ fn read_ips_from_file( #[cfg(test)] mod tests { - use super::{parse_addresses, Opts}; + use super::{parse_addresses, parse_addresses_with_resolver, Opts}; use std::net::{IpAddr, Ipv4Addr}; + #[test] + fn literal_targets_and_exclusions_do_not_initialize_a_resolver() { + let opts = Opts { + addresses: vec![ + "192.0.2.0/30".to_owned(), + "192.0.2.2".to_owned(), + "2001:db8::/126".to_owned(), + "2001:db8::3".to_owned(), + ], + exclude_addresses: Some(vec![ + "192.0.2.0/31".to_owned(), + "192.0.2.3".to_owned(), + "2001:db8::/127".to_owned(), + "2001:db8::3".to_owned(), + ]), + ..Default::default() + }; + + let ips = parse_addresses_with_resolver(&opts, || { + panic!("literal targets and exclusions must not initialize DNS") + }); + + assert_eq!( + ips, + [ + "192.0.2.2".parse::().unwrap(), + "2001:db8::2".parse::().unwrap(), + ] + ); + } + + #[test] + fn empty_targets_do_not_initialize_a_resolver() { + assert!(parse_addresses_with_resolver(&Opts::default(), || { + panic!("empty targets must not initialize DNS") + }) + .is_empty()); + } + #[test] fn parse_correct_addresses() { let opts = Opts { From bd5571f5d8c0934cb900a10dd15cd200810184fa Mon Sep 17 00:00:00 2001 From: bee Date: Thu, 1 Oct 2026 18:56:25 +0100 Subject: [PATCH 2/4] Record lazy DNS startup benchmark results --- docs/lazy-dns-benchmark-results.json | 92 ++++++++++++++++++++++++++++ docs/lazy-dns-benchmark.md | 50 +++++++++++++++ 2 files changed, 142 insertions(+) create mode 100644 docs/lazy-dns-benchmark-results.json create mode 100644 docs/lazy-dns-benchmark.md diff --git a/docs/lazy-dns-benchmark-results.json b/docs/lazy-dns-benchmark-results.json new file mode 100644 index 00000000..eabe0681 --- /dev/null +++ b/docs/lazy-dns-benchmark-results.json @@ -0,0 +1,92 @@ +{"metadata": {"base": "eae9fce582b28b198ffded0dfacc491025f1e239", "head": "a810e17ed26e1978def99701f007aa185b9a96e2", "date": "2026-10-01", "cpu": "Intel Core Ultra 7 165U", "kernel": "7.2.6-1-cachyos", "hosts_file_bytes": 2760051, "trials": 20, "warmups": 2, "scanner_cpus": "0-3", "profile": "release with LTO", "binary_sha256": {"before": "669627834d8a32f60e2167e78a9518dcede7562831adb85fb61a9d94871494b8", "lazy-dns": "968ebbe0bc6f4d8ff1379d98eb700d94391f4c95cf66865c5cedc513eefcb323"}, "cases": {"literal_ipv4": ["-a", "127.0.0.1"], "mixed_cidrs_and_exclusions": ["-a", "127.0.0.1,192.0.2.0/30,2001:db8::/126", "--exclude-addresses", "192.0.2.1,2001:db8::1"]}, "summary": {"literal_ipv4": {"before": 107.92008100042949, "lazy-dns": 1.8471019998287375}, "mixed_cidrs_and_exclusions": {"before": 108.3773515001667, "lazy-dns": 1.889162000225042}}}, + "samples": [ + {"case": "literal_ipv4", "variant": "before", "trial": -2, "warmup": true, "wall_ms": 108.80524999993213}, + {"case": "literal_ipv4", "variant": "lazy-dns", "trial": -2, "warmup": true, "wall_ms": 18.250492000333907}, + {"case": "literal_ipv4", "variant": "lazy-dns", "trial": -1, "warmup": true, "wall_ms": 1.5691499993408797}, + {"case": "literal_ipv4", "variant": "before", "trial": -1, "warmup": true, "wall_ms": 107.43746499974804}, + {"case": "literal_ipv4", "variant": "before", "trial": 0, "warmup": false, "wall_ms": 105.66421500061551}, + {"case": "literal_ipv4", "variant": "lazy-dns", "trial": 0, "warmup": false, "wall_ms": 2.1487020003405632}, + {"case": "literal_ipv4", "variant": "lazy-dns", "trial": 1, "warmup": false, "wall_ms": 1.4123829996606219}, + {"case": "literal_ipv4", "variant": "before", "trial": 1, "warmup": false, "wall_ms": 108.50232099983259}, + {"case": "literal_ipv4", "variant": "before", "trial": 2, "warmup": false, "wall_ms": 109.79825400045229}, + {"case": "literal_ipv4", "variant": "lazy-dns", "trial": 2, "warmup": false, "wall_ms": 1.8868950000978657}, + {"case": "literal_ipv4", "variant": "lazy-dns", "trial": 3, "warmup": false, "wall_ms": 1.3932640003986307}, + {"case": "literal_ipv4", "variant": "before", "trial": 3, "warmup": false, "wall_ms": 109.61606500040944}, + {"case": "literal_ipv4", "variant": "before", "trial": 4, "warmup": false, "wall_ms": 107.01633200005745}, + {"case": "literal_ipv4", "variant": "lazy-dns", "trial": 4, "warmup": false, "wall_ms": 1.9506320004438749}, + {"case": "literal_ipv4", "variant": "lazy-dns", "trial": 5, "warmup": false, "wall_ms": 1.511264000328083}, + {"case": "literal_ipv4", "variant": "before", "trial": 5, "warmup": false, "wall_ms": 106.61665300085588}, + {"case": "literal_ipv4", "variant": "before", "trial": 6, "warmup": false, "wall_ms": 106.65007999978116}, + {"case": "literal_ipv4", "variant": "lazy-dns", "trial": 6, "warmup": false, "wall_ms": 2.104817000144976}, + {"case": "literal_ipv4", "variant": "lazy-dns", "trial": 7, "warmup": false, "wall_ms": 3.400986000087869}, + {"case": "literal_ipv4", "variant": "before", "trial": 7, "warmup": false, "wall_ms": 108.03813600068679}, + {"case": "literal_ipv4", "variant": "before", "trial": 8, "warmup": false, "wall_ms": 112.29763299979822}, + {"case": "literal_ipv4", "variant": "lazy-dns", "trial": 8, "warmup": false, "wall_ms": 1.8402639998384984}, + {"case": "literal_ipv4", "variant": "lazy-dns", "trial": 9, "warmup": false, "wall_ms": 1.5964510002959287}, + {"case": "literal_ipv4", "variant": "before", "trial": 9, "warmup": false, "wall_ms": 106.39107299994066}, + {"case": "literal_ipv4", "variant": "before", "trial": 10, "warmup": false, "wall_ms": 107.79217400067864}, + {"case": "literal_ipv4", "variant": "lazy-dns", "trial": 10, "warmup": false, "wall_ms": 1.8669159999262774}, + {"case": "literal_ipv4", "variant": "lazy-dns", "trial": 11, "warmup": false, "wall_ms": 1.463550000153191}, + {"case": "literal_ipv4", "variant": "before", "trial": 11, "warmup": false, "wall_ms": 107.80202600017219}, + {"case": "literal_ipv4", "variant": "before", "trial": 12, "warmup": false, "wall_ms": 116.3139880000017}, + {"case": "literal_ipv4", "variant": "lazy-dns", "trial": 12, "warmup": false, "wall_ms": 2.2172799999680137}, + {"case": "literal_ipv4", "variant": "lazy-dns", "trial": 13, "warmup": false, "wall_ms": 1.6738979993533576}, + {"case": "literal_ipv4", "variant": "before", "trial": 13, "warmup": false, "wall_ms": 106.9011989993669}, + {"case": "literal_ipv4", "variant": "before", "trial": 14, "warmup": false, "wall_ms": 108.78321700056404}, + {"case": "literal_ipv4", "variant": "lazy-dns", "trial": 14, "warmup": false, "wall_ms": 1.88298700049927}, + {"case": "literal_ipv4", "variant": "lazy-dns", "trial": 15, "warmup": false, "wall_ms": 1.5814200005479506}, + {"case": "literal_ipv4", "variant": "before", "trial": 15, "warmup": false, "wall_ms": 104.41276900019147}, + {"case": "literal_ipv4", "variant": "before", "trial": 16, "warmup": false, "wall_ms": 109.80787399967085}, + {"case": "literal_ipv4", "variant": "lazy-dns", "trial": 16, "warmup": false, "wall_ms": 2.2769460001654807}, + {"case": "literal_ipv4", "variant": "lazy-dns", "trial": 17, "warmup": false, "wall_ms": 1.4284320004662732}, + {"case": "literal_ipv4", "variant": "before", "trial": 17, "warmup": false, "wall_ms": 104.55902600006084}, + {"case": "literal_ipv4", "variant": "before", "trial": 18, "warmup": false, "wall_ms": 109.07295600009093}, + {"case": "literal_ipv4", "variant": "lazy-dns", "trial": 18, "warmup": false, "wall_ms": 1.8539399998189765}, + {"case": "literal_ipv4", "variant": "lazy-dns", "trial": 19, "warmup": false, "wall_ms": 1.4077169998927275}, + {"case": "literal_ipv4", "variant": "before", "trial": 19, "warmup": false, "wall_ms": 110.57459000039671}, + {"case": "mixed_cidrs_and_exclusions", "variant": "before", "trial": -2, "warmup": true, "wall_ms": 110.40175900052418}, + {"case": "mixed_cidrs_and_exclusions", "variant": "lazy-dns", "trial": -2, "warmup": true, "wall_ms": 2.437932000248111}, + {"case": "mixed_cidrs_and_exclusions", "variant": "lazy-dns", "trial": -1, "warmup": true, "wall_ms": 1.5238009991662693}, + {"case": "mixed_cidrs_and_exclusions", "variant": "before", "trial": -1, "warmup": true, "wall_ms": 110.08191400014766}, + {"case": "mixed_cidrs_and_exclusions", "variant": "before", "trial": 0, "warmup": false, "wall_ms": 105.82008699930157}, + {"case": "mixed_cidrs_and_exclusions", "variant": "lazy-dns", "trial": 0, "warmup": false, "wall_ms": 2.1583729994745227}, + {"case": "mixed_cidrs_and_exclusions", "variant": "lazy-dns", "trial": 1, "warmup": false, "wall_ms": 1.6641169995637028}, + {"case": "mixed_cidrs_and_exclusions", "variant": "before", "trial": 1, "warmup": false, "wall_ms": 109.03231500014954}, + {"case": "mixed_cidrs_and_exclusions", "variant": "before", "trial": 2, "warmup": false, "wall_ms": 111.66701000001922}, + {"case": "mixed_cidrs_and_exclusions", "variant": "lazy-dns", "trial": 2, "warmup": false, "wall_ms": 1.9898759992429405}, + {"case": "mixed_cidrs_and_exclusions", "variant": "lazy-dns", "trial": 3, "warmup": false, "wall_ms": 1.6310500004692585}, + {"case": "mixed_cidrs_and_exclusions", "variant": "before", "trial": 3, "warmup": false, "wall_ms": 112.38924600002065}, + {"case": "mixed_cidrs_and_exclusions", "variant": "before", "trial": 4, "warmup": false, "wall_ms": 105.65431600025477}, + {"case": "mixed_cidrs_and_exclusions", "variant": "lazy-dns", "trial": 4, "warmup": false, "wall_ms": 3.717132000019774}, + {"case": "mixed_cidrs_and_exclusions", "variant": "lazy-dns", "trial": 5, "warmup": false, "wall_ms": 1.6103719999591704}, + {"case": "mixed_cidrs_and_exclusions", "variant": "before", "trial": 5, "warmup": false, "wall_ms": 110.49120000006951}, + {"case": "mixed_cidrs_and_exclusions", "variant": "before", "trial": 6, "warmup": false, "wall_ms": 108.23442800028715}, + {"case": "mixed_cidrs_and_exclusions", "variant": "lazy-dns", "trial": 6, "warmup": false, "wall_ms": 1.9596680003814981}, + {"case": "mixed_cidrs_and_exclusions", "variant": "lazy-dns", "trial": 7, "warmup": false, "wall_ms": 1.4453109997702995}, + {"case": "mixed_cidrs_and_exclusions", "variant": "before", "trial": 7, "warmup": false, "wall_ms": 110.5336709997573}, + {"case": "mixed_cidrs_and_exclusions", "variant": "before", "trial": 8, "warmup": false, "wall_ms": 107.15662799975689}, + {"case": "mixed_cidrs_and_exclusions", "variant": "lazy-dns", "trial": 8, "warmup": false, "wall_ms": 1.8957000002046698}, + {"case": "mixed_cidrs_and_exclusions", "variant": "lazy-dns", "trial": 9, "warmup": false, "wall_ms": 1.4613819994337973}, + {"case": "mixed_cidrs_and_exclusions", "variant": "before", "trial": 9, "warmup": false, "wall_ms": 108.52699599945481}, + {"case": "mixed_cidrs_and_exclusions", "variant": "before", "trial": 10, "warmup": false, "wall_ms": 106.66815299919108}, + {"case": "mixed_cidrs_and_exclusions", "variant": "lazy-dns", "trial": 10, "warmup": false, "wall_ms": 1.8602290001581423}, + {"case": "mixed_cidrs_and_exclusions", "variant": "lazy-dns", "trial": 11, "warmup": false, "wall_ms": 1.4934349992472562}, + {"case": "mixed_cidrs_and_exclusions", "variant": "before", "trial": 11, "warmup": false, "wall_ms": 108.72595399996499}, + {"case": "mixed_cidrs_and_exclusions", "variant": "before", "trial": 12, "warmup": false, "wall_ms": 106.78846599967073}, + {"case": "mixed_cidrs_and_exclusions", "variant": "lazy-dns", "trial": 12, "warmup": false, "wall_ms": 1.8826240002454142}, + {"case": "mixed_cidrs_and_exclusions", "variant": "lazy-dns", "trial": 13, "warmup": false, "wall_ms": 1.7505579999124166}, + {"case": "mixed_cidrs_and_exclusions", "variant": "before", "trial": 13, "warmup": false, "wall_ms": 106.40540900021733}, + {"case": "mixed_cidrs_and_exclusions", "variant": "before", "trial": 14, "warmup": false, "wall_ms": 106.3447010001255}, + {"case": "mixed_cidrs_and_exclusions", "variant": "lazy-dns", "trial": 14, "warmup": false, "wall_ms": 1.9092600005023996}, + {"case": "mixed_cidrs_and_exclusions", "variant": "lazy-dns", "trial": 15, "warmup": false, "wall_ms": 2.155000000129803}, + {"case": "mixed_cidrs_and_exclusions", "variant": "before", "trial": 15, "warmup": false, "wall_ms": 106.64889799954835}, + {"case": "mixed_cidrs_and_exclusions", "variant": "before", "trial": 16, "warmup": false, "wall_ms": 107.53761800060602}, + {"case": "mixed_cidrs_and_exclusions", "variant": "lazy-dns", "trial": 16, "warmup": false, "wall_ms": 2.302744000189705}, + {"case": "mixed_cidrs_and_exclusions", "variant": "lazy-dns", "trial": 17, "warmup": false, "wall_ms": 1.9342010000400478}, + {"case": "mixed_cidrs_and_exclusions", "variant": "before", "trial": 17, "warmup": false, "wall_ms": 109.41427300076612}, + {"case": "mixed_cidrs_and_exclusions", "variant": "before", "trial": 18, "warmup": false, "wall_ms": 109.9792039995009}, + {"case": "mixed_cidrs_and_exclusions", "variant": "lazy-dns", "trial": 18, "warmup": false, "wall_ms": 2.0170340003460296}, + {"case": "mixed_cidrs_and_exclusions", "variant": "lazy-dns", "trial": 19, "warmup": false, "wall_ms": 1.366477999908966}, + {"case": "mixed_cidrs_and_exclusions", "variant": "before", "trial": 19, "warmup": false, "wall_ms": 108.52027500004624} + ] +} diff --git a/docs/lazy-dns-benchmark.md b/docs/lazy-dns-benchmark.md new file mode 100644 index 00000000..375f4078 --- /dev/null +++ b/docs/lazy-dns-benchmark.md @@ -0,0 +1,50 @@ +# Lazy DNS initialization benchmark + +Compared the Tokio build at `eae9fce582b28b198ffded0dfacc491025f1e239` with the lazy-resolver implementation +at `a810e17ed26e1978def99701f007aa185b9a96e2` on 2026-10-01. + +## Method + +Both binaries are release builds with LTO, compiled using Rust 1.98.1 on an +Intel Core Ultra 7 165U running Linux 7.2.6-1-cachyos. Each workload ran twenty +measured times plus two warmups per binary, alternating A/B and B/A order. +Both binaries were restricted to CPUs 0-3; the harness used CPUs 8-9. + +Every invocation excluded its only requested port, so this measures full CLI +startup and address parsing without sending scan traffic. The runs used a +private network namespace with only loopback. Configuration and scripts were +disabled. No builds ran concurrently with the measurement. + +Common arguments: + +```sh +--no-config --config-path /dev/null --no-banner --scripts none --greppable \ + --ports 80 --exclude-ports 80 +``` + +The IPv4 case adds `-a 127.0.0.1`. The mixed case adds +`-a 127.0.0.1,192.0.2.0/30,2001:db8::/126` and +`--exclude-addresses 192.0.2.1,2001:db8::1`. Both use `RUST_LOG=info`. + +## Results + +| Workload | Before, median CLI time | Lazy DNS, median CLI time | Time saved | +| --- | ---: | ---: | ---: | +| Literal IPv4 | 107.92 ms | 1.85 ms | 106.07 ms (98.29%) | +| IPv4/IPv6 CIDRs and exclusions | 108.38 ms | 1.89 ms | 106.49 ms (98.26%) | + +All 88 invocations exited successfully with the expected empty scan output. +A separate syscall trace of the literal-IP invocation confirmed no reads of +`/etc/hosts` or `/etc/resolv.conf` and no network connects or sends. + +This host has a 2,760,051-byte hosts file. Eager Hickory initialization parsed +that file even when only numeric addresses were requested. Deferring the +resolver removes that cost; systems with smaller hosts files will save less. +This is a startup measurement, not a measurement of socket throughput. +Hostname and file lookup precedence are unchanged. A hostname that needs the +fallback resolver still pays its initialization cost, once per parse operation. + +[Raw timings and binary hashes](lazy-dns-benchmark-results.json) are included. +Regression tests use a resolver factory that panics if called, verifying that +IPv4/IPv6 literals, CIDRs, exclusions, duplicates and empty target lists stay +independent of DNS initialization. No hostname lookups were added to the tests. From b0dedb6700d340d46dd7573af760275d3331c959 Mon Sep 17 00:00:00 2001 From: bee Date: Fri, 2 Oct 2026 10:29:57 +0100 Subject: [PATCH 3/4] docs(perf): remeasure lazy DNS against merged Tokio master --- docs/lazy-dns-benchmark-results.json | 240 +++++++++++++++++---------- docs/lazy-dns-benchmark.md | 56 +++---- 2 files changed, 176 insertions(+), 120 deletions(-) diff --git a/docs/lazy-dns-benchmark-results.json b/docs/lazy-dns-benchmark-results.json index eabe0681..0f25f5e6 100644 --- a/docs/lazy-dns-benchmark-results.json +++ b/docs/lazy-dns-benchmark-results.json @@ -1,92 +1,150 @@ -{"metadata": {"base": "eae9fce582b28b198ffded0dfacc491025f1e239", "head": "a810e17ed26e1978def99701f007aa185b9a96e2", "date": "2026-10-01", "cpu": "Intel Core Ultra 7 165U", "kernel": "7.2.6-1-cachyos", "hosts_file_bytes": 2760051, "trials": 20, "warmups": 2, "scanner_cpus": "0-3", "profile": "release with LTO", "binary_sha256": {"before": "669627834d8a32f60e2167e78a9518dcede7562831adb85fb61a9d94871494b8", "lazy-dns": "968ebbe0bc6f4d8ff1379d98eb700d94391f4c95cf66865c5cedc513eefcb323"}, "cases": {"literal_ipv4": ["-a", "127.0.0.1"], "mixed_cidrs_and_exclusions": ["-a", "127.0.0.1,192.0.2.0/30,2001:db8::/126", "--exclude-addresses", "192.0.2.1,2001:db8::1"]}, "summary": {"literal_ipv4": {"before": 107.92008100042949, "lazy-dns": 1.8471019998287375}, "mixed_cidrs_and_exclusions": {"before": 108.3773515001667, "lazy-dns": 1.889162000225042}}}, - "samples": [ - {"case": "literal_ipv4", "variant": "before", "trial": -2, "warmup": true, "wall_ms": 108.80524999993213}, - {"case": "literal_ipv4", "variant": "lazy-dns", "trial": -2, "warmup": true, "wall_ms": 18.250492000333907}, - {"case": "literal_ipv4", "variant": "lazy-dns", "trial": -1, "warmup": true, "wall_ms": 1.5691499993408797}, - {"case": "literal_ipv4", "variant": "before", "trial": -1, "warmup": true, "wall_ms": 107.43746499974804}, - {"case": "literal_ipv4", "variant": "before", "trial": 0, "warmup": false, "wall_ms": 105.66421500061551}, - {"case": "literal_ipv4", "variant": "lazy-dns", "trial": 0, "warmup": false, "wall_ms": 2.1487020003405632}, - {"case": "literal_ipv4", "variant": "lazy-dns", "trial": 1, "warmup": false, "wall_ms": 1.4123829996606219}, - {"case": "literal_ipv4", "variant": "before", "trial": 1, "warmup": false, "wall_ms": 108.50232099983259}, - {"case": "literal_ipv4", "variant": "before", "trial": 2, "warmup": false, "wall_ms": 109.79825400045229}, - {"case": "literal_ipv4", "variant": "lazy-dns", "trial": 2, "warmup": false, "wall_ms": 1.8868950000978657}, - {"case": "literal_ipv4", "variant": "lazy-dns", "trial": 3, "warmup": false, "wall_ms": 1.3932640003986307}, - {"case": "literal_ipv4", "variant": "before", "trial": 3, "warmup": false, "wall_ms": 109.61606500040944}, - {"case": "literal_ipv4", "variant": "before", "trial": 4, "warmup": false, "wall_ms": 107.01633200005745}, - {"case": "literal_ipv4", "variant": "lazy-dns", "trial": 4, "warmup": false, "wall_ms": 1.9506320004438749}, - {"case": "literal_ipv4", "variant": "lazy-dns", "trial": 5, "warmup": false, "wall_ms": 1.511264000328083}, - {"case": "literal_ipv4", "variant": "before", "trial": 5, "warmup": false, "wall_ms": 106.61665300085588}, - {"case": "literal_ipv4", "variant": "before", "trial": 6, "warmup": false, "wall_ms": 106.65007999978116}, - {"case": "literal_ipv4", "variant": "lazy-dns", "trial": 6, "warmup": false, "wall_ms": 2.104817000144976}, - {"case": "literal_ipv4", "variant": "lazy-dns", "trial": 7, "warmup": false, "wall_ms": 3.400986000087869}, - {"case": "literal_ipv4", "variant": "before", "trial": 7, "warmup": false, "wall_ms": 108.03813600068679}, - {"case": "literal_ipv4", "variant": "before", "trial": 8, "warmup": false, "wall_ms": 112.29763299979822}, - {"case": "literal_ipv4", "variant": "lazy-dns", "trial": 8, "warmup": false, "wall_ms": 1.8402639998384984}, - {"case": "literal_ipv4", "variant": "lazy-dns", "trial": 9, "warmup": false, "wall_ms": 1.5964510002959287}, - {"case": "literal_ipv4", "variant": "before", "trial": 9, "warmup": false, "wall_ms": 106.39107299994066}, - {"case": "literal_ipv4", "variant": "before", "trial": 10, "warmup": false, "wall_ms": 107.79217400067864}, - {"case": "literal_ipv4", "variant": "lazy-dns", "trial": 10, "warmup": false, "wall_ms": 1.8669159999262774}, - {"case": "literal_ipv4", "variant": "lazy-dns", "trial": 11, "warmup": false, "wall_ms": 1.463550000153191}, - {"case": "literal_ipv4", "variant": "before", "trial": 11, "warmup": false, "wall_ms": 107.80202600017219}, - {"case": "literal_ipv4", "variant": "before", "trial": 12, "warmup": false, "wall_ms": 116.3139880000017}, - {"case": "literal_ipv4", "variant": "lazy-dns", "trial": 12, "warmup": false, "wall_ms": 2.2172799999680137}, - {"case": "literal_ipv4", "variant": "lazy-dns", "trial": 13, "warmup": false, "wall_ms": 1.6738979993533576}, - {"case": "literal_ipv4", "variant": "before", "trial": 13, "warmup": false, "wall_ms": 106.9011989993669}, - {"case": "literal_ipv4", "variant": "before", "trial": 14, "warmup": false, "wall_ms": 108.78321700056404}, - {"case": "literal_ipv4", "variant": "lazy-dns", "trial": 14, "warmup": false, "wall_ms": 1.88298700049927}, - {"case": "literal_ipv4", "variant": "lazy-dns", "trial": 15, "warmup": false, "wall_ms": 1.5814200005479506}, - {"case": "literal_ipv4", "variant": "before", "trial": 15, "warmup": false, "wall_ms": 104.41276900019147}, - {"case": "literal_ipv4", "variant": "before", "trial": 16, "warmup": false, "wall_ms": 109.80787399967085}, - {"case": "literal_ipv4", "variant": "lazy-dns", "trial": 16, "warmup": false, "wall_ms": 2.2769460001654807}, - {"case": "literal_ipv4", "variant": "lazy-dns", "trial": 17, "warmup": false, "wall_ms": 1.4284320004662732}, - {"case": "literal_ipv4", "variant": "before", "trial": 17, "warmup": false, "wall_ms": 104.55902600006084}, - {"case": "literal_ipv4", "variant": "before", "trial": 18, "warmup": false, "wall_ms": 109.07295600009093}, - {"case": "literal_ipv4", "variant": "lazy-dns", "trial": 18, "warmup": false, "wall_ms": 1.8539399998189765}, - {"case": "literal_ipv4", "variant": "lazy-dns", "trial": 19, "warmup": false, "wall_ms": 1.4077169998927275}, - {"case": "literal_ipv4", "variant": "before", "trial": 19, "warmup": false, "wall_ms": 110.57459000039671}, - {"case": "mixed_cidrs_and_exclusions", "variant": "before", "trial": -2, "warmup": true, "wall_ms": 110.40175900052418}, - {"case": "mixed_cidrs_and_exclusions", "variant": "lazy-dns", "trial": -2, "warmup": true, "wall_ms": 2.437932000248111}, - {"case": "mixed_cidrs_and_exclusions", "variant": "lazy-dns", "trial": -1, "warmup": true, "wall_ms": 1.5238009991662693}, - {"case": "mixed_cidrs_and_exclusions", "variant": "before", "trial": -1, "warmup": true, "wall_ms": 110.08191400014766}, - {"case": "mixed_cidrs_and_exclusions", "variant": "before", "trial": 0, "warmup": false, "wall_ms": 105.82008699930157}, - {"case": "mixed_cidrs_and_exclusions", "variant": "lazy-dns", "trial": 0, "warmup": false, "wall_ms": 2.1583729994745227}, - {"case": "mixed_cidrs_and_exclusions", "variant": "lazy-dns", "trial": 1, "warmup": false, "wall_ms": 1.6641169995637028}, - {"case": "mixed_cidrs_and_exclusions", "variant": "before", "trial": 1, "warmup": false, "wall_ms": 109.03231500014954}, - {"case": "mixed_cidrs_and_exclusions", "variant": "before", "trial": 2, "warmup": false, "wall_ms": 111.66701000001922}, - {"case": "mixed_cidrs_and_exclusions", "variant": "lazy-dns", "trial": 2, "warmup": false, "wall_ms": 1.9898759992429405}, - {"case": "mixed_cidrs_and_exclusions", "variant": "lazy-dns", "trial": 3, "warmup": false, "wall_ms": 1.6310500004692585}, - {"case": "mixed_cidrs_and_exclusions", "variant": "before", "trial": 3, "warmup": false, "wall_ms": 112.38924600002065}, - {"case": "mixed_cidrs_and_exclusions", "variant": "before", "trial": 4, "warmup": false, "wall_ms": 105.65431600025477}, - {"case": "mixed_cidrs_and_exclusions", "variant": "lazy-dns", "trial": 4, "warmup": false, "wall_ms": 3.717132000019774}, - {"case": "mixed_cidrs_and_exclusions", "variant": "lazy-dns", "trial": 5, "warmup": false, "wall_ms": 1.6103719999591704}, - {"case": "mixed_cidrs_and_exclusions", "variant": "before", "trial": 5, "warmup": false, "wall_ms": 110.49120000006951}, - {"case": "mixed_cidrs_and_exclusions", "variant": "before", "trial": 6, "warmup": false, "wall_ms": 108.23442800028715}, - {"case": "mixed_cidrs_and_exclusions", "variant": "lazy-dns", "trial": 6, "warmup": false, "wall_ms": 1.9596680003814981}, - {"case": "mixed_cidrs_and_exclusions", "variant": "lazy-dns", "trial": 7, "warmup": false, "wall_ms": 1.4453109997702995}, - {"case": "mixed_cidrs_and_exclusions", "variant": "before", "trial": 7, "warmup": false, "wall_ms": 110.5336709997573}, - {"case": "mixed_cidrs_and_exclusions", "variant": "before", "trial": 8, "warmup": false, "wall_ms": 107.15662799975689}, - {"case": "mixed_cidrs_and_exclusions", "variant": "lazy-dns", "trial": 8, "warmup": false, "wall_ms": 1.8957000002046698}, - {"case": "mixed_cidrs_and_exclusions", "variant": "lazy-dns", "trial": 9, "warmup": false, "wall_ms": 1.4613819994337973}, - {"case": "mixed_cidrs_and_exclusions", "variant": "before", "trial": 9, "warmup": false, "wall_ms": 108.52699599945481}, - {"case": "mixed_cidrs_and_exclusions", "variant": "before", "trial": 10, "warmup": false, "wall_ms": 106.66815299919108}, - {"case": "mixed_cidrs_and_exclusions", "variant": "lazy-dns", "trial": 10, "warmup": false, "wall_ms": 1.8602290001581423}, - {"case": "mixed_cidrs_and_exclusions", "variant": "lazy-dns", "trial": 11, "warmup": false, "wall_ms": 1.4934349992472562}, - {"case": "mixed_cidrs_and_exclusions", "variant": "before", "trial": 11, "warmup": false, "wall_ms": 108.72595399996499}, - {"case": "mixed_cidrs_and_exclusions", "variant": "before", "trial": 12, "warmup": false, "wall_ms": 106.78846599967073}, - {"case": "mixed_cidrs_and_exclusions", "variant": "lazy-dns", "trial": 12, "warmup": false, "wall_ms": 1.8826240002454142}, - {"case": "mixed_cidrs_and_exclusions", "variant": "lazy-dns", "trial": 13, "warmup": false, "wall_ms": 1.7505579999124166}, - {"case": "mixed_cidrs_and_exclusions", "variant": "before", "trial": 13, "warmup": false, "wall_ms": 106.40540900021733}, - {"case": "mixed_cidrs_and_exclusions", "variant": "before", "trial": 14, "warmup": false, "wall_ms": 106.3447010001255}, - {"case": "mixed_cidrs_and_exclusions", "variant": "lazy-dns", "trial": 14, "warmup": false, "wall_ms": 1.9092600005023996}, - {"case": "mixed_cidrs_and_exclusions", "variant": "lazy-dns", "trial": 15, "warmup": false, "wall_ms": 2.155000000129803}, - {"case": "mixed_cidrs_and_exclusions", "variant": "before", "trial": 15, "warmup": false, "wall_ms": 106.64889799954835}, - {"case": "mixed_cidrs_and_exclusions", "variant": "before", "trial": 16, "warmup": false, "wall_ms": 107.53761800060602}, - {"case": "mixed_cidrs_and_exclusions", "variant": "lazy-dns", "trial": 16, "warmup": false, "wall_ms": 2.302744000189705}, - {"case": "mixed_cidrs_and_exclusions", "variant": "lazy-dns", "trial": 17, "warmup": false, "wall_ms": 1.9342010000400478}, - {"case": "mixed_cidrs_and_exclusions", "variant": "before", "trial": 17, "warmup": false, "wall_ms": 109.41427300076612}, - {"case": "mixed_cidrs_and_exclusions", "variant": "before", "trial": 18, "warmup": false, "wall_ms": 109.9792039995009}, - {"case": "mixed_cidrs_and_exclusions", "variant": "lazy-dns", "trial": 18, "warmup": false, "wall_ms": 2.0170340003460296}, - {"case": "mixed_cidrs_and_exclusions", "variant": "lazy-dns", "trial": 19, "warmup": false, "wall_ms": 1.366477999908966}, - {"case": "mixed_cidrs_and_exclusions", "variant": "before", "trial": 19, "warmup": false, "wall_ms": 108.52027500004624} - ] +{ + "metadata": { + "base": "b7119f7f3eb1601e81126ef3572699ed7b3b7c0b", + "candidate": "bd5571f5d8c0934cb900a10dd15cd200810184fa", + "environment": "Linux-7.2.6-1-cachyos-x86_64-with-glibc2.44", + "rust": "rustc 1.98.1 (48a229cea 2026-09-01) (Arch Linux rust 1:1.98.1-1.1)", + "hosts_bytes": 2760051, + "profile": "release with LTO", + "common_args": [ + "--no-config", + "--config-path", + "/dev/null", + "--no-banner", + "--scripts", + "none", + "--greppable", + "--ports", + "80", + "--exclude-ports", + "80" + ], + "workloads": { + "literal-ipv4": [ + "-a", + "127.0.0.1" + ], + "mixed-cidrs": [ + "-a", + "127.0.0.1,192.0.2.0/30,2001:db8::/126", + "--exclude-addresses", + "192.0.2.1,2001:db8::1" + ] + }, + "warmups_each": 2, + "samples_each": 20, + "binary_cpus": "0-3", + "harness_cpus": "8-9", + "binary_sha256": { + "base": "592084468184592eccd6eb6c034ec5082c4d87cfb98830a356cafd2840895660", + "dns": "df3d9ec3dc0cb06f0f22eb78a5d931501e8dc732e8ec964821664b2639757b63" + } + }, + "summary": { + "literal-ipv4": { + "base_ms": 163.940108, + "dns_ms": 2.509731, + "samples_each": 20 + }, + "mixed-cidrs": { + "base_ms": 156.416927, + "dns_ms": 2.828561, + "samples_each": 20 + } + }, + "samples": { + "literal-ipv4": { + "base": [ + 215.897718, + 183.823791, + 175.253542, + 163.773817, + 147.115293, + 164.326923, + 177.33364, + 158.094141, + 150.186893, + 143.755972, + 198.600258, + 172.165225, + 157.560206, + 164.052818, + 163.827398, + 156.789986, + 168.904366, + 164.52782, + 156.405881, + 154.640973 + ], + "dns": [ + 4.250775, + 6.259614, + 2.766641, + 2.157366, + 4.590757, + 2.363155, + 3.606774, + 2.939905, + 2.26549, + 2.302657, + 2.594393, + 2.192749, + 2.304999, + 2.55503, + 2.491389, + 2.199853, + 2.274247, + 2.005264, + 2.528073, + 3.944459 + ] + }, + "mixed-cidrs": { + "base": [ + 160.128434, + 156.649324, + 179.480969, + 156.18453, + 165.469259, + 176.904758, + 165.883161, + 194.900821, + 166.629997, + 147.115791, + 143.570861, + 141.100268, + 134.591861, + 138.817171, + 137.906366, + 134.771879, + 164.06809, + 135.593559, + 184.674193, + 155.142553 + ], + "dns": [ + 2.9847, + 3.993055, + 4.875872, + 2.782137, + 2.707159, + 2.9424, + 2.874985, + 2.646729, + 3.113046, + 1.858364, + 2.324747, + 1.972527, + 3.047183, + 2.172364, + 2.708645, + 2.284746, + 2.736481, + 3.252555, + 3.175199, + 2.925109 + ] + } + }, + "invocations": 88 } diff --git a/docs/lazy-dns-benchmark.md b/docs/lazy-dns-benchmark.md index 375f4078..82de2740 100644 --- a/docs/lazy-dns-benchmark.md +++ b/docs/lazy-dns-benchmark.md @@ -1,19 +1,19 @@ # Lazy DNS initialization benchmark -Compared the Tokio build at `eae9fce582b28b198ffded0dfacc491025f1e239` with the lazy-resolver implementation -at `a810e17ed26e1978def99701f007aa185b9a96e2` on 2026-10-01. +Compared current Tokio master `b7119f7f3eb1601e81126ef3572699ed7b3b7c0b` with the lazy-resolver implementation +at `bd5571f5d8c0934cb900a10dd15cd200810184fa` on 2026-10-02. ## Method -Both binaries are release builds with LTO, compiled using Rust 1.98.1 on an -Intel Core Ultra 7 165U running Linux 7.2.6-1-cachyos. Each workload ran twenty -measured times plus two warmups per binary, alternating A/B and B/A order. -Both binaries were restricted to CPUs 0-3; the harness used CPUs 8-9. +Both binaries are release builds with LTO, using Rust 1.98.1 on an Intel Core +Ultra 7 165U running Linux 7.2.6-1-cachyos. Each workload used twenty measured +runs and two warmups per binary, alternating A/B and B/A order. Binaries used +CPUs 0-3; the harness used CPUs 8-9. No builds ran during measurement. -Every invocation excluded its only requested port, so this measures full CLI -startup and address parsing without sending scan traffic. The runs used a -private network namespace with only loopback. Configuration and scripts were -disabled. No builds ran concurrently with the measurement. +The harness ran in a private network namespace. Every invocation excluded +its only requested port, so no scan traffic was sent. Configuration and +scripts were disabled. Timing spans process launch through exit, including +the same `taskset` affinity launcher for both builds. Common arguments: @@ -22,29 +22,27 @@ Common arguments: --ports 80 --exclude-ports 80 ``` -The IPv4 case adds `-a 127.0.0.1`. The mixed case adds +The literal case adds `-a 127.0.0.1`. The mixed case adds `-a 127.0.0.1,192.0.2.0/30,2001:db8::/126` and -`--exclude-addresses 192.0.2.1,2001:db8::1`. Both use `RUST_LOG=info`. +`--exclude-addresses 192.0.2.1,2001:db8::1`. Both use `RUST_LOG=rustscan=info`. ## Results -| Workload | Before, median CLI time | Lazy DNS, median CLI time | Time saved | +| Workload | Master median | Lazy DNS median | Time saved | | --- | ---: | ---: | ---: | -| Literal IPv4 | 107.92 ms | 1.85 ms | 106.07 ms (98.29%) | -| IPv4/IPv6 CIDRs and exclusions | 108.38 ms | 1.89 ms | 106.49 ms (98.26%) | +| Literal IPv4 | 163.94 ms | 2.51 ms | 161.43 ms (98.47%) | +| IPv4/IPv6 CIDRs and exclusions | 156.42 ms | 2.83 ms | 153.59 ms (98.19%) | All 88 invocations exited successfully with the expected empty scan output. -A separate syscall trace of the literal-IP invocation confirmed no reads of -`/etc/hosts` or `/etc/resolv.conf` and no network connects or sends. - -This host has a 2,760,051-byte hosts file. Eager Hickory initialization parsed -that file even when only numeric addresses were requested. Deferring the -resolver removes that cost; systems with smaller hosts files will save less. -This is a startup measurement, not a measurement of socket throughput. -Hostname and file lookup precedence are unchanged. A hostname that needs the -fallback resolver still pays its initialization cost, once per parse operation. - -[Raw timings and binary hashes](lazy-dns-benchmark-results.json) are included. -Regression tests use a resolver factory that panics if called, verifying that -IPv4/IPv6 literals, CIDRs, exclusions, duplicates and empty target lists stay -independent of DNS initialization. No hostname lookups were added to the tests. +A separate syscall trace of the optimized literal-IP invocation recorded no +reads of `/etc/hosts` or `/etc/resolv.conf` and no network connects or sends. + +This host has a 2,760,051-byte hosts file. Eager Hickory initialization parses +that file even for numeric targets. Systems with smaller hosts files will +save less; this measures CLI startup, not socket throughput. Hostnames that +need fallback DNS still pay resolver initialization once, and parsing order, +file handling, deduplication and exclusions keep their existing behavior. + +[Raw samples, setup and binary hashes](lazy-dns-benchmark-results.json) are +included. Network-free regression tests verify that literal IPv4/IPv6 targets, +CIDRs, exclusions, duplicates and empty inputs do not construct the resolver. From e3abce7ce984d70045c93f62106d013491b80ed9 Mon Sep 17 00:00:00 2001 From: bee Date: Fri, 2 Oct 2026 12:33:19 +0100 Subject: [PATCH 4/4] docs(perf): verify lazy DNS on current master --- docs/lazy-dns-benchmark-results.json | 177 ++++++++++++++------------- docs/lazy-dns-benchmark.md | 8 +- 2 files changed, 93 insertions(+), 92 deletions(-) diff --git a/docs/lazy-dns-benchmark-results.json b/docs/lazy-dns-benchmark-results.json index 0f25f5e6..80059f09 100644 --- a/docs/lazy-dns-benchmark-results.json +++ b/docs/lazy-dns-benchmark-results.json @@ -1,11 +1,12 @@ { "metadata": { - "base": "b7119f7f3eb1601e81126ef3572699ed7b3b7c0b", - "candidate": "bd5571f5d8c0934cb900a10dd15cd200810184fa", + "base": "67c08a33100362c54b56fde784b0fd234f70fa11", + "candidate": "a05592a8a88b77ad85d961137943dfadfe98b612", "environment": "Linux-7.2.6-1-cachyos-x86_64-with-glibc2.44", "rust": "rustc 1.98.1 (48a229cea 2026-09-01) (Arch Linux rust 1:1.98.1-1.1)", "hosts_bytes": 2760051, "profile": "release with LTO", + "network_namespace": "unshare --user --map-root-user --net", "common_args": [ "--no-config", "--config-path", @@ -36,113 +37,113 @@ "binary_cpus": "0-3", "harness_cpus": "8-9", "binary_sha256": { - "base": "592084468184592eccd6eb6c034ec5082c4d87cfb98830a356cafd2840895660", - "dns": "df3d9ec3dc0cb06f0f22eb78a5d931501e8dc732e8ec964821664b2639757b63" + "base": "4d6b090218ff36249ed95f14ec1a82626e8ea33854f3823f19a6de247b1524b8", + "dns": "a9d6bf949f56c53d18cc85bc9b53b21bd85a63bcdd04ad78992d392c675c77ac" } }, "summary": { "literal-ipv4": { - "base_ms": 163.940108, - "dns_ms": 2.509731, + "base_ms": 168.23068849999999, + "dns_ms": 2.248762, "samples_each": 20 }, "mixed-cidrs": { - "base_ms": 156.416927, - "dns_ms": 2.828561, + "base_ms": 178.0855925, + "dns_ms": 2.4539600000000004, "samples_each": 20 } }, "samples": { "literal-ipv4": { "base": [ - 215.897718, - 183.823791, - 175.253542, - 163.773817, - 147.115293, - 164.326923, - 177.33364, - 158.094141, - 150.186893, - 143.755972, - 198.600258, - 172.165225, - 157.560206, - 164.052818, - 163.827398, - 156.789986, - 168.904366, - 164.52782, - 156.405881, - 154.640973 + 143.391226, + 146.562804, + 149.615525, + 151.188597, + 152.269193, + 159.499601, + 164.926958, + 164.347529, + 167.208931, + 165.433184, + 172.246939, + 169.252446, + 172.777899, + 170.729249, + 170.092681, + 171.863255, + 169.612842, + 170.857396, + 173.117403, + 175.206345 ], "dns": [ - 4.250775, - 6.259614, - 2.766641, - 2.157366, - 4.590757, - 2.363155, - 3.606774, - 2.939905, - 2.26549, - 2.302657, - 2.594393, - 2.192749, - 2.304999, - 2.55503, - 2.491389, - 2.199853, - 2.274247, - 2.005264, - 2.528073, - 3.944459 + 2.241793, + 1.817341, + 2.39956, + 2.048986, + 3.123401, + 1.820017, + 3.615094, + 2.165312, + 2.675535, + 2.103261, + 2.531392, + 2.215141, + 2.572939, + 2.063803, + 2.671431, + 2.059846, + 2.598858, + 2.230916, + 2.678259, + 2.255731 ] }, "mixed-cidrs": { "base": [ - 160.128434, - 156.649324, - 179.480969, - 156.18453, - 165.469259, - 176.904758, - 165.883161, - 194.900821, - 166.629997, - 147.115791, - 143.570861, - 141.100268, - 134.591861, - 138.817171, - 137.906366, - 134.771879, - 164.06809, - 135.593559, - 184.674193, - 155.142553 + 175.504767, + 178.797842, + 186.183728, + 176.885958, + 177.989816, + 180.028568, + 177.66299, + 174.757221, + 175.468485, + 175.328023, + 177.639639, + 175.637593, + 177.922435, + 185.394396, + 182.587204, + 180.58311, + 178.961137, + 178.293186, + 180.482419, + 178.181369 ], "dns": [ - 2.9847, - 3.993055, - 4.875872, - 2.782137, - 2.707159, - 2.9424, - 2.874985, - 2.646729, - 3.113046, - 1.858364, - 2.324747, - 1.972527, - 3.047183, - 2.172364, - 2.708645, - 2.284746, - 2.736481, - 3.252555, - 3.175199, - 2.925109 + 3.275193, + 2.114074, + 2.700771, + 2.183317, + 2.606538, + 2.368046, + 2.599702, + 2.238105, + 2.683892, + 2.292249, + 2.528366, + 2.114478, + 2.668921, + 2.103271, + 3.275514, + 2.27974, + 3.103311, + 2.265298, + 2.580743, + 2.379554 ] } }, diff --git a/docs/lazy-dns-benchmark.md b/docs/lazy-dns-benchmark.md index 82de2740..ed5e4e5b 100644 --- a/docs/lazy-dns-benchmark.md +++ b/docs/lazy-dns-benchmark.md @@ -1,7 +1,7 @@ # Lazy DNS initialization benchmark -Compared current Tokio master `b7119f7f3eb1601e81126ef3572699ed7b3b7c0b` with the lazy-resolver implementation -at `bd5571f5d8c0934cb900a10dd15cd200810184fa` on 2026-10-02. +Compared current Tokio master `67c08a33100362c54b56fde784b0fd234f70fa11` with the lazy-resolver implementation +at `a05592a8a88b77ad85d961137943dfadfe98b612` on 2026-10-02. ## Method @@ -30,8 +30,8 @@ The literal case adds `-a 127.0.0.1`. The mixed case adds | Workload | Master median | Lazy DNS median | Time saved | | --- | ---: | ---: | ---: | -| Literal IPv4 | 163.94 ms | 2.51 ms | 161.43 ms (98.47%) | -| IPv4/IPv6 CIDRs and exclusions | 156.42 ms | 2.83 ms | 153.59 ms (98.19%) | +| Literal IPv4 | 168.23 ms | 2.25 ms | 165.98 ms (98.66%) | +| IPv4/IPv6 CIDRs and exclusions | 178.09 ms | 2.45 ms | 175.63 ms (98.62%) | All 88 invocations exited successfully with the expected empty scan output. A separate syscall trace of the optimized literal-IP invocation recorded no