vivaldi_nc/lib.rs
1//! Vivaldi network coordinates for fast, distributed latency estimates in multinode networks, with
2//! a clean and simple interface.
3//!
4//! Network Coordinates (NC) are a way to represent a node's position in a network's
5//! latency space. Nodes with low latency (ping or round trip time) between each
6//! other will be close to each other in this latency space. Nodes with high latency between them
7//! will be far from each other.
8//!
9//! This is an implementation of Vivaldi Network Coordinates, a specific NC
10//! algorithm, with a simple interface and few dependencies. Vivaldi coordinates
11//! are typically used in distributed networking applications, like p2p networks.
12//! They allow each node in the network to estimate its position in a latency space
13//! in a distributed way, with no central authority. This enables nodes to
14//! understand estimated latency to any other node in the system.
15//!
16//! To learn more, see the [Vivaldi coordinates article on
17//! Wikipedia](https://en.wikipedia.org/wiki/Vivaldi_coordinates) or [the original
18//! paper](http://conferences.sigcomm.org/sigcomm/2004/papers/p426-dabek111111.pdf) (Frank Dabek,
19//! Russ Cox, Frans Kaashoek, Robert Morris (2004)).
20//!
21//! # Usage
22//!
23//! This crate exports a single struct, [`NetworkCoordinate`] and two type aliases
24//! ([`NetworkCoordinate2D`] and [`NetworkCoordinate3D`]). Typical use of Vivaldi NCs for a
25//! distributed network works like this:
26//!
27//! 1. Each node in the network has its own instance of [`NetworkCoordinate`]. *See "Note on
28//! dimensionality" below.*
29//! 2. Every node occasionally sends its [`NetworkCoordinate`] to some or all other nodes through
30//! the network overlay.
31//! 3. Whenever a node receives a remote coordinate, it updates its local coordinate with the
32//! actual measured round trip time (RTT or "ping time") between itself and that node to improve
33//! its own position and thus reduce its estimation error.
34//! 4. Any node can estimate its RTT to any other [`NetworkCoordinate`] it's aware of.
35//!
36//! Importantly, all updates in this system are performed locally. No central authority is needed
37//! to build the network latency maps. It's fully distributed.
38//!
39//! **Note on dimensionality:** Typically 2D or 3D Vivaldi coordinates (i.e. `NetworkCoordinate<2>` or
40//! `NetworkCoordinate<3>`) are sufficient. Higher dimensions don't add much accuracy and aren't
41//! generally worth it. That said, you're welcome to use any dimension you like.
42//!
43//! # Examples
44//!
45//! In the first example, we simulate receving a remote NC, measuring ping, and updating our NC
46//! accordingly.
47//!
48//! ```
49//! use vivaldi_nc::NetworkCoordinate;
50//!
51//! // create our local NC as a 3-dimensional Vivaldi coordinate
52//! let mut my_nc = NetworkCoordinate::<3>::new();
53//!
54//! // mock up a remote NC for the sake of this example (normally the node would actually receive
55//! // this from a remote node)
56//! let received_msg = "{\"position\":[1.5,0.5,2.0],\"height\":0.1,\"error\":1.0}";
57//! let remote_nc: NetworkCoordinate<3> = serde_json::from_str(received_msg).unwrap();
58//!
59//! // mock up a measured RTT between us and that node (normally the nodes would coordinate
60//! // measuring this together)
61//! let rtt_actual = std::time::Duration::from_millis(78);
62//!
63//! // with the actual RTT in hand, we can update our NC to improve its accuracy
64//! my_nc.update(&remote_nc, rtt_actual);
65//!
66//! // by doing this iteratively (and forever), all NCs in the network will converge to better
67//! // represent the actual latency space of the network
68//! ```
69//!
70//! In this second example, we simulate receving a NC from another node indirectly; likely
71//! forwarded to us by someone else. And in this case, we aren't measuring the actual RTT. Instead,
72//! we're using the NCs to estimate RTT.
73//!
74//! This example also uses the type alias [`NetworkCoordinate3D`] instead of its equivalent
75//! [`NetworkCoordinate<3>`].
76//!
77//! ```
78//! use vivaldi_nc::NetworkCoordinate3D;
79//!
80//! // create our local NC as a 3-dimensional Vivaldi coordinate
81//! let mut my_nc = NetworkCoordinate3D::new();
82//!
83//! // mock up a remote NC for the sake of this example (normally the node would actually receive
84//! // this from a remote node)
85//! let received_msg = "{\"position\":[1.5,0.5,2.0],\"height\":0.1,\"error\":1.0}";
86//! let remote_nc: NetworkCoordinate3D = serde_json::from_str(received_msg).unwrap();
87//!
88//! // estimate the RTT to this remote node without measuring it directly
89//! let rtt_estimated = my_nc.estimated_rtt(&remote_nc);
90//!
91//! // so with just the knowledge of another NC, we can get reasonably good estimates of RTT
92//! // without actually needing to measure it
93//! ```
94//!
95
96#![deny(
97 clippy::all,
98 clippy::correctness,
99 clippy::style,
100 clippy::suspicious,
101 clippy::complexity,
102 clippy::perf,
103 clippy::cargo,
104 clippy::pedantic,
105 clippy::nursery,
106 clippy::unwrap_used
107)]
108#![deny(
109 anonymous_parameters,
110 missing_copy_implementations,
111 missing_debug_implementations,
112 missing_docs,
113 nonstandard_style,
114 rust_2018_idioms,
115 single_use_lifetimes,
116 trivial_casts,
117 trivial_numeric_casts,
118 // unreachable_pub, // disagrees with clippy::nurclippy::nursery as of 13-02-2023
119 unused_extern_crates,
120 unused_qualifications,
121 variant_size_differences
122)]
123#![allow(clippy::type_repetition_in_bounds)]
124#![allow(single_use_lifetimes)]
125
126mod height_vector;
127mod vector;
128
129// publish our interface
130pub mod network_coordinate;
131pub use network_coordinate::NetworkCoordinate;
132pub use network_coordinate::NetworkCoordinate2D;
133pub use network_coordinate::NetworkCoordinate3D;