This document describes the timing configuration system introduced in ftr v0.3.1 to eliminate hardcoded timing values and enable runtime configuration.
The timing configuration system provides a centralized way to manage all timing-related parameters in ftr. This addresses the issue of hardcoded delays and polling intervals that were scattered throughout the codebase, making it difficult to optimize performance for different environments.
Located in src/traceroute/config.rs, the TimingConfig structure contains all timing parameters:
pub struct TimingConfig {
/// Receiver thread polling interval (default: 100ms)
pub receiver_poll_interval: Duration,
/// Main wait loop polling interval (default: 10ms)
pub main_loop_poll_interval: Duration,
/// Enrichment completion wait time (default: 100ms)
pub enrichment_wait_time: Duration,
/// Socket read timeout (default: 100ms)
pub socket_read_timeout: Duration,
/// UDP socket retry delay (default: 10ms)
pub udp_retry_delay: Duration,
}
The src/config/timing.rs module provides:
pub const DEFAULT_SOCKET_READ_TIMEOUT_MS: u64 = 100;
pub const DEFAULT_UDP_RETRY_DELAY_MS: u64 = 10;
pub const DEFAULT_RECEIVER_POLL_INTERVAL_MS: u64 = 100;
pub const DEFAULT_MAIN_LOOP_POLL_INTERVAL_MS: u64 = 10;
pub const DEFAULT_ENRICHMENT_WAIT_TIME_MS: u64 = 100;
use crate::config::timing;
// Get the current socket read timeout
let timeout = timing::socket_read_timeout();
// Set custom configuration at startup
let custom_config = TimingConfig {
socket_read_timeout: Duration::from_millis(50),
// ... other fields
};
timing::set_config(custom_config)?;
All socket implementations now use the timing configuration:
windows.rs, windows_async.rs): Uses socket_read_timeout()icmp_v4.rs): Uses socket_read_timeout() for recv operationsudp.rs): Uses udp_retry_delay() for retry loopsThe main traceroute engine (engine.rs) uses:
receiver_poll_interval() for the receiver threadmain_loop_poll_interval() for the main wait loopenrichment_wait_time() for enrichment completionThe async implementation passes TimingConfig directly to async sockets, allowing immediate response processing without polling.
If you’re using ftr as a library and want to customize timing:
use ftr::{TracerouteConfig, TimingConfig};
use std::time::Duration;
// Create custom timing configuration
let timing = TimingConfig {
socket_read_timeout: Duration::from_millis(50),
receiver_poll_interval: Duration::from_millis(50),
main_loop_poll_interval: Duration::from_millis(5),
enrichment_wait_time: Duration::from_millis(50),
udp_retry_delay: Duration::from_millis(5),
};
// Apply to traceroute config
let config = TracerouteConfig::builder()
.target("example.com")
.timing_config(timing)
.build()?;
When adding new time-based operations:
src/config/timing.rsTimingConfig