java.lang.Object
net.i2p.router.JobImpl
net.i2p.router.peermanager.PeerTestJob
All Implemented Interfaces:
Job

public class PeerTestJobextends JobImpl
Periodically tests selected peers to gather real-time performance data and update peer profiles.

This job runs continuously when enabled, selecting peers based on bandwidth tier, reachability, and version compatibility. Tests are performed by sending a DatabaseStoreMessage containing the peer's own RouterInfo back to itself through the tunnel system, measuring response times and connectivity.

Peer Selection Criteria:

  • High-bandwidth tiers (O, P, X) with reachability capability
  • Version 0.9.57+ for compatibility
  • Configurable concurrency based on system resources

Performance Impact:

  • Adaptive delays based on system load and uptime
  • CPU throttling when load exceeds 80%
  • Automatic timeout adjustment based on historical test times

Future Considerations:

  • Evaluate necessity of peer testing in current network conditions
  • Consider alternative test methods beyond RI self-messaging
  • Integration with PeerManager.selectPeers() optimization
  • Field Details

    • _log

      private final Log _log
      Logger for peer tests.
    • _manager

      private PeerManager _manager
      The peer manager we report results to.
    • _keepTesting

      private boolean _keepTesting
      Whether to continue testing.
    • _priorityPeers

      private final List<Hash> _priorityPeers
      Peers tested before the random ones.
    • DEFAULT_PEER_TEST_DELAY

      private static final long DEFAULT_PEER_TEST_DELAY
      Default delay between peer tests.
      See Also:
    • PROP_PEER_TEST_DELAY

      public static final String PROP_PEER_TEST_DELAY
      Property key setting the pause before a peer test starts.
      See Also:
    • DEFAULT_PEER_TEST_CONCURRENCY

      private static final int DEFAULT_PEER_TEST_CONCURRENCY
      Default number of peers to test concurrently.
      See Also:
    • PROP_PEER_TEST_CONCURRENCY

      public static final String PROP_PEER_TEST_CONCURRENCY
      Property key setting how many peers are tested at once.
      See Also:
    • DEFAULT_PEER_TEST_TIMEOUT

      private static final int DEFAULT_PEER_TEST_TIMEOUT
      Default timeout in milliseconds.
      See Also:
    • PROP_PEER_TEST_TIMEOUT

      public static final String PROP_PEER_TEST_TIMEOUT
      Property key setting how long a peer test may take, in milliseconds.
      See Also:
    • STARTUP_PHASE_MS

      private static final long STARTUP_PHASE_MS
      Uptime threshold for the aggressive startup profiling phase (4 hours).
      See Also:
    • WARMUP_PHASE_MS

      private static final long WARMUP_PHASE_MS
      Uptime threshold for the warm-up decay phase (12 hours).
      See Also:
    • STARTUP_DELAY_MS

      private static final long STARTUP_DELAY_MS
      Delay during the aggressive startup phase.
      See Also:
    • WARMUP_DELAY_MS

      private static final long WARMUP_DELAY_MS
      Delay during the warm-up decay phase.
      See Also:
    • STEADY_DELAY_MS

      private static final long STEADY_DELAY_MS
      Delay during steady state.
      See Also:
  • Constructor Details

    • PeerTestJob

      public PeerTestJob(RouterContext context)
      Creates a new PeerTestJob instance and initializes required statistics.
      Parameters:
      context - the router context for accessing services like logging and statistics
  • Method Details

    • getAvgPeerTestTime

      public int getAvgPeerTestTime()
      Average successful peer test time over the last minute.
      Returns:
      average test time in milliseconds, or 0 if no context available
    • getTotalAvgPeerTestTime

      public int getTotalAvgPeerTestTime()
      Total average peer test time over the last hour, including slow tests.
      Returns:
      total average test time in milliseconds, or 0 if no context available
    • getPeerTestDelay

      private long getPeerTestDelay()
      Calculates the delay before starting the next round of peer tests.

      Three-phase decay based on uptime:

      • 0–4 hours (startup): 3s — aggressively profile all fast peers
      • 4–12 hours (warm-up): 5s — ramp down while keeping data fresh
      • 12+ hours (steady): 8s — maintenance cadence

      User override via PROP_PEER_TEST_DELAY is respected for the steady-state value only; startup and warm-up phases use hardcoded values.

      Returns:
      delay in milliseconds before next test round
    • getTestTimeout

      private int getTestTimeout()
      Determines the timeout for individual peer tests with automatic adjustment.

      Ensures timeout is never set below the average successful test time to avoid false timeouts during normal operation.

      Returns:
      timeout in milliseconds, adjusted if necessary
    • getTestConcurrency

      private int getTestConcurrency()
      Determines the number of peers to test concurrently based on router uptime.

      Three-phase decay:

      • 0–4 hours (startup): 4 — profile all fast peers quickly
      • 4–12 hours (warm-up): 3 — ramp down
      • 12+ hours (steady): 1 — maintenance cadence

      Concurrency is limited to 1 when CPU load exceeds 95% to prevent system overload.

      Returns:
      number of peers to test in parallel
    • startTesting

      public void startTesting(PeerManager manager)
      Starts the peer testing process.

      Schedules the first test run with the configured delay. If uptime is under 3 minutes, the log notes that testing will commence shortly.

      Parameters:
      manager - the peer manager to use for peer selection
    • stopTesting

      public void stopTesting()
      Stops the peer testing process gracefully.

      The current test round will complete, but no new rounds will be scheduled.

    • schedulePriorityTests

      public void schedulePriorityTests(List<Hash> peers)
      Schedule peers for priority testing (e.g., from slow tunnels). These peers will be tested on the next test cycle before other peers.
      Parameters:
      peers - list of peer hashes to test urgently
    • getName

      public String getName()
      Name of this job.
      Returns:
      the name this job is listed under in the job queue and the logs, "Test Peers"
    • runJob

      public void runJob()
      Main job execution loop that performs peer testing with adaptive scheduling.

      Process flow:

      1. Check if testing should continue
      2. Select peers for testing based on criteria
      3. Test each selected peer
      4. Adapt next run delay based on system conditions

      Adaptive Behavior:

      • Skip the round and multiply delay by 5 if job lag > 2000ms
      • Scale delay proportionally to lag (1 + lag/500, capped at 5 min) if job lag > 300ms or CPU load > 80%
      • Normal delay otherwise
    • selectPeersToTest

      private Set<RouterInfo> selectPeersToTest()
      Selects peers for testing based on performance and capability criteria.

      Selection Criteria:

      • Priority: peers recorded from slow tunnels, tested first
      • Regular: all profiled peers with a RouterInfo and version 0.9.57+, sorted by tier priority then staleness
      • Excluded: Missing local RouterInfo or profile, or a version older than 0.9.57

      Performance Impact:

      • Uses cached lookups to minimize database queries
      • Pre-parses capabilities to avoid repeated string operations
      • Logs skipped peers with specific reasons for debugging
      Returns:
      set of RouterInfo structures for testing (excluding self)
    • testPeer

      private void testPeer(RouterInfo peer)
      Fire off the necessary jobs and messages to test the given peer The message is a store of the peer's RI to itself, with a reply token.
      Parameters:
      peer - the peer to test
    • getOutboundTunnelId

      private TunnelInfo getOutboundTunnelId()
      What tunnel will we send the test out through?
      Returns:
      tunnel id (or null if none are found)
    • getInboundTunnelId

      private TunnelInfo getInboundTunnelId()
      What tunnel will we get replies through?
      Returns:
      tunnel id (or null if none are found)
    • buildMessage

      private DatabaseStoreMessage buildMessage(RouterInfo peer, TunnelId replyTunnel, Hash replyGateway, long nonce, long expiration)
      Build a message to test the peer with. The message is a store of the peer's RI to itself, with a reply token.
      Parameters:
      peer - the peer whose own RouterInfo is stored back to it
      replyTunnel - the id of our inbound tunnel the reply must return through
      replyGateway - the hash of that tunnel's gateway, asked to forward the reply
      nonce - the reply token echoed in the response so we can match it to this test
      expiration - the message expiration time in ms since epoch
      Returns:
      the assembled DatabaseStoreMessage carrying the reply token
    • tierRank

      private static int tierRank(ProfileOrganizer organizer, Hash peer)
      Selection priority for a test candidate: tier first (fast 0, high-cap 1, other 2), then staleness of the persisted tunnel-test EWMA so never-tested peers go first.

      Precomputed by tierRank(ProfileOrganizer, Hash) rather than derived from ProfileOrganizer.isFast/isHighCapacity inside the comparator: those take the reorganize read lock, and calling them per comparison meant 4 lock acquisitions per comparison across an O(n log n) sort.

      Parameters:
      organizer - the profile organizer holding the fast and high-capacity sets
      peer - the test candidate whose tier is ranked
      Returns:
      0 for fast, 1 for high capacity, 2 for everything else