clean up export, add module level docs

- public NetworkCoordinate so it’s easer to just `use vivaldi_nc::NetworkCoordinate`
- add module level docs and examples in lib.rs
- cleanup README

Signed-off-by: Stephen Waits <steve@waits.net>
This commit is contained in:
swaits committed 2023-02-04 10:39:59 -07:00
1 parent c83a4e654b
commit e9febc6faa
3 files changed
+143 -13

No files matched your search

+48 -10
View File
@@ -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. uses this structure to track its latency position in the entire network.
```rust ```rust
use vivaldi_nc::network_coordinate::NetworkCoordinate; use vivaldi_nc::NetworkCoordinate;
// create a 2-dimensional NetworkCoordinate to track my position // create a 2-dimensional NetworkCoordinate to track my position
let mut my_position = NetworkCoordinate::<2>::new(); 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 and compact binary formats like [bincode](https://crates.io/crates/bincode) and
[MessagePack](https://github.com/3Hren/msgpack-rust). [MessagePack](https://github.com/3Hren/msgpack-rust).
### Features
### Examples
## Dependencies ## Dependencies
One design goal of this crate is to minimize dependencies. When dependencies One design goal of this crate is to minimize dependencies. When dependencies
@@ -131,7 +127,7 @@ This crate depends on:
`Vector<T,N>` uses a const generic length, we use this to help derive `Vector<T,N>` uses a const generic length, we use this to help derive
`Deserialize`. `Deserialize`.
## Alternative implementations ## Design Goals & Alternatives
Several crates implemented Vivaldi NC before this one. So, why another? 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. rigamarole. Support `serde` traits by default.
4. Well documented. Well tested. This varies by the crates. 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. All of that said, those other rust implementations might work best for you.
Here are the ones I know of today: 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) - [violin](https://crates.io/crates/violin)
- [vivaldi](https://crates.io/crates/vivaldi) - [vivaldi](https://crates.io/crates/vivaldi)
## Other Algorithms ### Other NC Algorithms
Vivaldi is about the simplest distributed NC algorithm out there. That Vivaldi is about the simplest distributed NC algorithm out there. That
simplicity combined with its reasonably good performance is a reason why it's 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: But it's far from the only choice. Here are links to other NC algorithms:
- TODO: list algorithms - [Pharos](https://en.wikipedia.org/wiki/Pharos_Network_Coordinates)
- TODO: list algorithms - [Phoenix](https://en.wikipedia.org/wiki/Phoenix_Network_Coordinates)
- TODO: list algorithms
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.
+92
View File
@@ -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 height_vector;
mod vector; mod vector;
// publish our interface
pub mod network_coordinate; pub mod network_coordinate;
pub use network_coordinate::NetworkCoordinate;
+3 -3
View File
@@ -65,7 +65,7 @@ impl<const N: usize> NetworkCoordinate<N> {
/// # Example /// # Example
/// ///
/// ``` /// ```
/// use vivaldi_nc::network_coordinate::NetworkCoordinate; /// use vivaldi_nc::NetworkCoordinate;
/// ///
/// // create a new 3-dimensional random NC /// // create a new 3-dimensional random NC
/// let a: NetworkCoordinate<3> = NetworkCoordinate::new(); /// let a: NetworkCoordinate<3> = NetworkCoordinate::new();
@@ -93,7 +93,7 @@ impl<const N: usize> NetworkCoordinate<N> {
/// # Example /// # 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 /// // 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. /// // NCs. In a real usecase these would have meaningful values.
@@ -125,7 +125,7 @@ impl<const N: usize> NetworkCoordinate<N> {
/// ///
/// ``` /// ```
/// use std::time::Duration; /// use std::time::Duration;
/// use vivaldi_nc::network_coordinate::NetworkCoordinate; /// use vivaldi_nc::NetworkCoordinate;
/// ///
/// // We always have our own NC: /// // We always have our own NC:
/// let mut local: NetworkCoordinate<2> = NetworkCoordinate::new(); /// let mut local: NetworkCoordinate<2> = NetworkCoordinate::new();