From 3347e5fe0d0922443f243aa691405b6767e4a63c Mon Sep 17 00:00:00 2001 From: Stephen Waits Date: Sat, 4 Feb 2023 10:39:59 -0700 Subject: [PATCH] =?UTF-8?q?docs:=20clean=20up=20export,=20add=20module=20l?= =?UTF-8?q?evel=20docs-=20public=20NetworkCoordinate=20so=20it=E2=80=99s?= =?UTF-8?q?=20easer=20to=20just=20`use=20vivaldi=5Fnc::NetworkCoordinate`-?= =?UTF-8?q?=20add=20module=20level=20docs=20and=20examples=20in=20lib.rs-?= =?UTF-8?q?=20cleanup=20READMESigned-off-by:=20Stephen=20Waits=20?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- README.md | 58 +++++++++++++++++++----- src/lib.rs | 92 +++++++++++++++++++++++++++++++++++++++ src/network_coordinate.rs | 6 +-- 3 files changed, 143 insertions(+), 13 deletions(-) diff --git a/README.md b/README.md index ce1506d..91b0b31 100644 --- a/README.md +++ b/README.md @@ -72,7 +72,7 @@ Each node in the network should create a `NetworkCoordinate` (NC). The node uses this structure to track its latency position in the entire network. ```rust -use vivaldi_nc::network_coordinate::NetworkCoordinate; +use vivaldi_nc::NetworkCoordinate; // create a 2-dimensional NetworkCoordinate to track my position let mut my_position = NetworkCoordinate::<2>::new(); @@ -107,10 +107,6 @@ by Serde, including text formats like [JSON](https://github.com/serde-rs/json) and compact binary formats like [bincode](https://crates.io/crates/bincode) and [MessagePack](https://github.com/3Hren/msgpack-rust). -### Features - -### Examples - ## Dependencies One design goal of this crate is to minimize dependencies. When dependencies @@ -131,7 +127,7 @@ This crate depends on: `Vector` uses a const generic length, we use this to help derive `Deserialize`. -## Alternative implementations +## Design Goals & Alternatives Several crates implemented Vivaldi NC before this one. So, why another? @@ -149,6 +145,8 @@ I had several design goals which the existing crates didn't satisfy: rigamarole. Support `serde` traits by default. 4. Well documented. Well tested. This varies by the crates. +### Other Vivaldi NC Implementations + All of that said, those other rust implementations might work best for you. Here are the ones I know of today: @@ -156,7 +154,7 @@ Here are the ones I know of today: - [violin](https://crates.io/crates/violin) - [vivaldi](https://crates.io/crates/vivaldi) -## Other Algorithms +### Other NC Algorithms Vivaldi is about the simplest distributed NC algorithm out there. That simplicity combined with its reasonably good performance is a reason why it's @@ -164,6 +162,46 @@ popular. But it's far from the only choice. Here are links to other NC algorithms: -- TODO: list algorithms -- TODO: list algorithms -- TODO: list algorithms +- [Pharos](https://en.wikipedia.org/wiki/Pharos_Network_Coordinates) +- [Phoenix](https://en.wikipedia.org/wiki/Phoenix_Network_Coordinates) + +Search your favorite research paper index for "network coordinates" and you'll +find many more. + +## Getting Help or Contributing + +To get help or discuss this crate, please use +[`vivaldi-nc-discuss@`](https://lists.sr.ht/~swaits/vivaldi-nc-discuss). + +Discussion related to development or patch submissions should go to +[`vivaldi-nc-devel@`](https://lists.sr.ht/~swaits/vivaldi-nc-devel). + +Patchsets should use [git-send-email](https://git-send-email.io/) or the [sr.ht +UI](https://git.sr.ht/~swaits/vivaldi-nc/send-email) (easiest IMO). + +Patch submitters implicitly agree that all contributions they submit fall under +the MIT license. + +## License + +> MIT License +> +> Copyright (c) 2023 Stephen Waits +> +> Permission is hereby granted, free of charge, to any person obtaining a copy +> of this software and associated documentation files (the "Software"), to deal +> in the Software without restriction, including without limitation the rights +> to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +> copies of the Software, and to permit persons to whom the Software is +> furnished to do so, subject to the following conditions: +> +> The above copyright notice and this permission notice shall be included in all +> copies or substantial portions of the Software. +> +> THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +> IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +> FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +> AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +> LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +> OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE +> SOFTWARE. diff --git a/src/lib.rs b/src/lib.rs index f6a7d25..f478808 100644 --- a/src/lib.rs +++ b/src/lib.rs @@ -1,4 +1,96 @@ +//! Vivaldi Network Coordinates with a simple interface +//! +//! Network Coordinates (NC) are a way to represent a node's position in a network's +//! latency space. Nodes with low latency (ping or round trip time) between each +//! other will be close to each other in this latency space. Nodes with high latency between them +//! will be far from each other. +//! +//! This is an implementation of Vivaldi Network Coordinates, a specific NC +//! algorithm, with a simple interface and few dependencies. Vivaldi coordinates +//! are typically used in distributed networking applications, like p2p networks. +//! They allow each node in the network to estimate its position in a latency space +//! in a distributed way, with no central authority. This enables nodes to +//! understand estimated latency to any other node in the system. +//! +//! To learn more, see the [Vivaldi coordinates article on +//! Wikipedia](https://en.wikipedia.org/wiki/Vivaldi_coordinates) or [the original +//! paper](http://conferences.sigcomm.org/sigcomm/2004/papers/p426-dabek111111.pdf) (Frank Dabek, +//! Russ Cox, Frans Kaashoek, Robert Morris (2004)). +//! +//! # Usage +//! +//! This crate exports a single struct, [`NetworkCoordinate`]. Typical use of Vivaldi NCs for a +//! distributed network works like this: +//! +//! 1. Each node in the network has its own instance of [`NetworkCoordinate`]. *See "Note on +//! dimensionality" below.* +//! 2. Every node occasionally sends its [`NetworkCoordinate`] to some or all other nodes through +//! the network overlay. +//! 3. Whenever a node receives a remote coordinate, it updates its local coordinate with the +//! actual measured round trip time (RTT or "ping time") between itself and that node to improve +//! its own position and thus reduce its estimation error. +//! 4. Any node can estimate its RTT to any other [`NetworkCoordinate`] it's aware of. +//! +//! Importantly, all updates in this system are performed locally. No central authority is needed +//! to build the network latency maps. It's fully distributed. +//! +//! **Note on dimensionality:** Typically 2D or 3D Vivaldi coordinates (i.e. `NetworkCoordinate<2>` or +//! `NetworkCoordinate<3>`) are sufficient. Higher dimensions don't add much accuracy and aren't +//! generally worth it. That said, you're welcome to use any dimension you like. +//! +//! # Examples +//! +//! In the first example, we simulate receving a remote NC, measuring ping, and updating our NC +//! accordingly. +//! +//! ``` +//! use vivaldi_nc::NetworkCoordinate; +//! +//! // create our local NC as a 3-dimensional Vivaldi coordinate +//! let mut my_nc = NetworkCoordinate::<3>::new(); +//! +//! // mock up a remote NC for the sake of this example (normally the node would actually receive +//! // this from a remote node) +//! let received_msg = "{\"position\":[{\"inner\":[1.5,0.5,2.0]},0.1],\"error\":1.0}"; +//! let remote_nc: NetworkCoordinate<3> = serde_json::from_str(received_msg).unwrap(); +//! +//! // mock up a measured RTT between us and that node (normally the nodes would coordinate +//! // measuring this together) +//! let rtt_actual = std::time::Duration::from_millis(78); +//! +//! // with the actual RTT in hand, we can update our NC to improve its accuracy +//! my_nc.update(&remote_nc, rtt_actual); +//! +//! // by doing this iteratively (and forever), all NCs in the network will converge to better +//! // represent the actual latency space of the network +//! ``` +//! +//! In this second example, we simulate receving a NC from another node indirectly; likely +//! forwarded to us by someone else. And in this case, we aren't measuring the actual RTT. Instead, +//! we're using the NCs to estimate RTT. +//! +//! ``` +//! use vivaldi_nc::NetworkCoordinate; +//! +//! // create our local NC as a 3-dimensional Vivaldi coordinate +//! let mut my_nc = NetworkCoordinate::<3>::new(); +//! +//! // mock up a remote NC for the sake of this example (normally the node would actually receive +//! // this from a remote node) +//! let received_msg = "{\"position\":[{\"inner\":[1.5,0.5,2.0]},0.1],\"error\":1.0}"; +//! let remote_nc: NetworkCoordinate<3> = serde_json::from_str(received_msg).unwrap(); +//! +//! // estimate the RTT to this remote node without measuring it directly +//! let rtt_estimated = my_nc.estimated_rtt(&remote_nc); +//! +//! // so with just the knowledge of another NC, we can get reasonably good estimates of RTT +//! // without actually needing to measure it +//! ``` +//! + mod height_vector; mod vector; +// publish our interface pub mod network_coordinate; +pub use network_coordinate::NetworkCoordinate; diff --git a/src/network_coordinate.rs b/src/network_coordinate.rs index 6940aa7..674c7a6 100644 --- a/src/network_coordinate.rs +++ b/src/network_coordinate.rs @@ -65,7 +65,7 @@ impl NetworkCoordinate { /// # Example /// /// ``` - /// use vivaldi_nc::network_coordinate::NetworkCoordinate; + /// use vivaldi_nc::NetworkCoordinate; /// /// // create a new 3-dimensional random NC /// let a: NetworkCoordinate<3> = NetworkCoordinate::new(); @@ -93,7 +93,7 @@ impl NetworkCoordinate { /// # Example /// /// ``` - /// use vivaldi_nc::network_coordinate::NetworkCoordinate; + /// use vivaldi_nc::NetworkCoordinate; /// /// // create some 2-dimensional NCs for the sake of this example. These will just be random /// // NCs. In a real usecase these would have meaningful values. @@ -125,7 +125,7 @@ impl NetworkCoordinate { /// /// ``` /// use std::time::Duration; - /// use vivaldi_nc::network_coordinate::NetworkCoordinate; + /// use vivaldi_nc::NetworkCoordinate; /// /// // We always have our own NC: /// let mut local: NetworkCoordinate<2> = NetworkCoordinate::new();