From 4f83c43824eea7be3619f235f8944d228eaa79cc Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Philipp=20Kr=C3=BCger?= Date: Mon, 26 Aug 2024 17:38:30 +0200 Subject: [PATCH] feat(bench): Add `--metrics` option printing iroh-net library metrics (#2668) MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit ## Description Used these changes to test #2667. I think this is a decent tool. Output looks like this:
$ cd iroh-net/bench && cargo run --release -- iroh --metrics --with-relay ``` Compiling iroh-net-bench v0.23.0 (/home/philipp/program/work/iroh/iroh-net/bench) Finished `release` profile [optimized + debuginfo] target(s) in 28.47s Running `/home/philipp/program/work/iroh/target/release/bulk iroh --metrics --with-relay` Client 0 stats: Connect time: 1008.829553ms Overall download stats: Transferred 1073741824 bytes on 1 streams in 1.70s (603.46 MiB/s) Time to first byte (TTFB): 105.312ms Total chunks: 36445 Average chunk time: 46.544ms Average chunk size: 28.77KiB Stream download metrics: │ Throughput │ Duration ──────┼───────────────┼────────── AVG │ 603.75 MiB/s │ 1.70s P0 │ 603.50 MiB/s │ 1.70s P10 │ 604.00 MiB/s │ 1.70s P50 │ 604.00 MiB/s │ 1.70s P90 │ 604.00 MiB/s │ 1.70s P100 │ 604.00 MiB/s │ 1.70s Metrics: MagicsockMetrics: { "actor_link_change": 0, "actor_tick_direct_addr_heartbeat": 0, "actor_tick_direct_addr_update_receiver": 6, "actor_tick_main": 22, "actor_tick_msg": 13, "actor_tick_other": 0, "actor_tick_portmap_changed": 0, "actor_tick_re_stun": 2, "num_direct_conns_added": 3, "num_direct_conns_removed": 1, "num_relay_conns_added": 5, "num_relay_conns_removed": 3, "re_stun_calls": 3, "recv_data_ipv4": 88975499264, "recv_data_ipv6": 0, "recv_data_relay": 49200, "recv_datagrams": 944499, "recv_disco_bad_key": 0, "recv_disco_bad_parse": 0, "recv_disco_call_me_maybe": 2, "recv_disco_call_me_maybe_bad_disco": 0, "recv_disco_ping": 14, "recv_disco_pong": 14, "recv_disco_relay": 6, "recv_disco_udp": 24, "relay_home_change": 2, "send_data": 1104903421, "send_data_network_down": 0, "send_disco_relay": 6, "send_disco_udp": 24, "send_ipv4": 1104905771, "send_ipv6": 470, "send_relay": 49988, "send_relay_error": 0, "sent_disco_call_me_maybe": 2, "sent_disco_ping": 14, "sent_disco_pong": 14, "sent_disco_relay": 6, "sent_disco_udp": 24, "update_direct_addrs": 3, } NetcheckMetrics: { "reports": 3, "reports_full": 0, "stun_packets_dropped": 0, "stun_packets_recv_ipv4": 0, "stun_packets_recv_ipv6": 0, "stun_packets_sent_ipv4": 10, "stun_packets_sent_ipv6": 10, } PortmapMetrics: { "external_address_updated": 0, "local_port_updates": 3, "mapping_attempts": 5, "mapping_failures": 3, "pcp_available": 0, "pcp_probes": 3, "probes_started": 3, "upnp_available": 0, "upnp_gateway_updated": 0, "upnp_probes": 6, "upnp_probes_failed": 3, } RelayMetrics: { "accepts": 2, "bytes_recv": 50082, "bytes_sent": 50082, "derp_accepts": 2, "disco_packets_dropped": 0, "disco_packets_recv": 0, "disco_packets_sent": 0, "disconnects": 0, "got_ping": 0, "other_packets_dropped": 0, "other_packets_recv": 2, "other_packets_sent": 0, "send_packets_dropped": 0, "send_packets_recv": 9, "send_packets_sent": 9, "sent_pong": 0, "unique_client_keys": 2, "unknown_frames": 0, "websocket_accepts": 0, } ```
## Breaking Changes None. The semver check also checks for the "public API" of `iroh-net/bench`, and there's been another `Opt` addition. ## Notes & open questions This PR is based on #2664 at the moment, let's merge that first. ## Change checklist - [x] Self-review. - ~~[ ] Documentation updates following the [style guide](https://rust-lang.github.io/rfcs/1574-more-api-documentation-conventions.html#appendix-a-full-conventions-text), if relevant.~~ - ~~[ ] Tests if relevant.~~ - [x] All breaking changes documented. --- Cargo.lock | 1 + iroh-net/bench/Cargo.toml | 1 + iroh-net/bench/src/bin/bulk.rs | 55 +++++++++++++++++++++++++++++ iroh-net/bench/src/lib.rs | 6 ++++ iroh-net/src/discovery/pkarr/dht.rs | 1 + 5 files changed, 64 insertions(+) diff --git a/Cargo.lock b/Cargo.lock index d303efee8a..2f8e76d693 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -2939,6 +2939,7 @@ dependencies = [ "clap", "futures-lite 2.3.0", "hdrhistogram", + "iroh-metrics", "iroh-net", "quinn 0.10.2", "rcgen 0.11.3", diff --git a/iroh-net/bench/Cargo.toml b/iroh-net/bench/Cargo.toml index ae53ed830d..892dde19dc 100644 --- a/iroh-net/bench/Cargo.toml +++ b/iroh-net/bench/Cargo.toml @@ -10,6 +10,7 @@ anyhow = "1.0.22" bytes = "1" hdrhistogram = { version = "7.2", default-features = false } iroh-net = { path = "..", features = ["test-utils"] } +iroh-metrics = { path = "../../iroh-metrics" } rcgen = "0.11.1" rustls = { version = "0.21.0", default-features = false, features = ["quic"] } clap = { version = "4", features = ["derive"] } diff --git a/iroh-net/bench/src/bin/bulk.rs b/iroh-net/bench/src/bin/bulk.rs index b81a7ee1c8..5ac3ba6a00 100644 --- a/iroh-net/bench/src/bin/bulk.rs +++ b/iroh-net/bench/src/bin/bulk.rs @@ -1,3 +1,5 @@ +use std::collections::BTreeMap; + use anyhow::Result; use clap::Parser; @@ -30,6 +32,19 @@ fn main() { } pub fn run_iroh(opt: Opt) -> Result<()> { + if opt.metrics { + // enable recording metrics + iroh_metrics::core::Core::try_init(|reg, metrics| { + use iroh_metrics::core::Metric; + metrics.insert(iroh_net::metrics::MagicsockMetrics::new(reg)); + metrics.insert(iroh_net::metrics::NetcheckMetrics::new(reg)); + metrics.insert(iroh_net::metrics::PortmapMetrics::new(reg)); + if opt.with_relay { + metrics.insert(iroh_net::metrics::RelayMetrics::new(reg)); + } + })?; + } + let server_span = tracing::error_span!("server"); let runtime = rt(); @@ -78,6 +93,30 @@ pub fn run_iroh(opt: Opt) -> Result<()> { } } + if opt.metrics { + // print metrics + let core = + iroh_metrics::core::Core::get().ok_or_else(|| anyhow::anyhow!("Missing metrics"))?; + println!("\nMetrics:"); + collect_and_print( + "MagicsockMetrics", + core.get_collector::(), + ); + collect_and_print( + "NetcheckMetrics", + core.get_collector::(), + ); + collect_and_print( + "PortmapMetrics", + core.get_collector::(), + ); + // if None, (this is the case if opt.with_relay is false), then this is skipped internally: + collect_and_print( + "RelayMetrics", + core.get_collector::(), + ); + } + server_thread.join().expect("server thread"); Ok(()) @@ -130,3 +169,19 @@ pub fn run_quinn(opt: Opt) -> Result<()> { pub fn run_s2n(_opt: s2n::Opt) -> Result<()> { unimplemented!() } + +fn collect_and_print( + category: &'static str, + metrics: Option<&impl iroh_metrics::struct_iterable::Iterable>, +) { + let Some(metrics) = metrics else { + return; + }; + let mut map = BTreeMap::new(); + for (name, counter) in metrics.iter() { + if let Some(counter) = counter.downcast_ref::() { + map.insert(name.to_string(), counter.get()); + } + } + println!("{category}: {map:#?}"); +} diff --git a/iroh-net/bench/src/lib.rs b/iroh-net/bench/src/lib.rs index b7ce6f10cb..e9bfc4272c 100644 --- a/iroh-net/bench/src/lib.rs +++ b/iroh-net/bench/src/lib.rs @@ -54,6 +54,12 @@ pub struct Opt { /// Show connection stats the at the end of the benchmark #[clap(long = "stats")] pub stats: bool, + /// Show iroh-net library counter metrics at the end of the benchmark + /// + /// These metrics are process-wide, so contain metrics for + /// clients and the server all summed up. + #[clap(long)] + pub metrics: bool, /// Whether to use the unordered read API #[clap(long = "unordered")] pub read_unordered: bool, diff --git a/iroh-net/src/discovery/pkarr/dht.rs b/iroh-net/src/discovery/pkarr/dht.rs index cc79aafda2..ff06e8dbaa 100644 --- a/iroh-net/src/discovery/pkarr/dht.rs +++ b/iroh-net/src/discovery/pkarr/dht.rs @@ -396,6 +396,7 @@ mod tests { use testresult::TestResult; #[tokio::test] + #[ignore = "flaky"] async fn dht_discovery_smoke() -> TestResult { let _ = tracing_subscriber::fmt::try_init(); let ep = crate::Endpoint::builder().bind(0).await?;