-
Notifications
You must be signed in to change notification settings - Fork 0
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
- Loading branch information
1 parent
227aa6f
commit 1fed6ea
Showing
23 changed files
with
1,394 additions
and
60 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,44 @@ | ||
# Benchmarking | ||
|
||
All benchmarks ran on a M1 Pro laptop running Asahi Linux. | ||
|
||
Check out our [codspeed results](https://codspeed.io/DuskSystems/wayfind/benchmarks) for a more accurate set of timings. | ||
|
||
## Context | ||
|
||
For all benchmarks, we percent-decode the path before matching. | ||
After matching, we convert any extracted parameters to strings. | ||
|
||
Some routers perform these operations automatically, while others require them to be done manually. | ||
|
||
We do this to try and match behaviour as best as possible. This is as close to an "apples-to-apples" comparison as we can get. | ||
|
||
## `matchit` inspired benches | ||
|
||
In a router of 130 routes, benchmark matching 4 paths. | ||
|
||
| Library | Time | Alloc Count | Alloc Size | Dealloc Count | Dealloc Size | | ||
|:-----------------|----------:|------------:|-----------:|--------------:|-------------:| | ||
| wayfind | 415.67 ns | 4 | 265 B | 4 | 265 B | | ||
| matchit | 559.16 ns | 4 | 416 B | 4 | 448 B | | ||
| path-tree | 570.10 ns | 4 | 416 B | 4 | 448 B | | ||
| xitca-router | 650.12 ns | 7 | 800 B | 7 | 832 B | | ||
| ntex-router | 2.2439 µs | 18 | 1.248 KB | 18 | 1.28 KB | | ||
| route-recognizer | 3.1662 µs | 160 | 8.505 KB | 160 | 8.537 KB | | ||
| routefinder | 6.2237 µs | 67 | 5.024 KB | 67 | 5.056 KB | | ||
| actix-router | 21.072 µs | 214 | 13.93 KB | 214 | 13.96 KB | | ||
|
||
## `path-tree` inspired benches | ||
|
||
In a router of 320 routes, benchmark matching 80 paths. | ||
|
||
| Library | Time | Alloc Count | Alloc Size | Dealloc Count | Dealloc Size | | ||
|:-----------------|----------:|------------:|-----------:|--------------:|-------------:| | ||
| wayfind | 5.9508 µs | 59 | 2.567 KB | 59 | 2.567 KB | | ||
| path-tree | 8.5983 µs | 59 | 7.447 KB | 59 | 7.47 KB | | ||
| matchit | 9.8800 µs | 140 | 17.81 KB | 140 | 17.83 KB | | ||
| xitca-router | 11.930 µs | 209 | 25.51 KB | 209 | 25.53 KB | | ||
| ntex-router | 35.919 µs | 201 | 19.54 KB | 201 | 19.56 KB | | ||
| route-recognizer | 69.604 µs | 2872 | 191.7 KB | 2872 | 204.8 KB | | ||
| routefinder | 87.659 µs | 525 | 48.40 KB | 525 | 48.43 KB | | ||
| actix-router | 187.49 µs | 2201 | 128.8 KB | 2201 | 128.8 KB | |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,10 @@ | ||
# TODO | ||
|
||
- Authority router. | ||
- Stop using the term 'route' to mean 'template'. | ||
- Split routers into seperate crates. | ||
- Dedupe the 2 tree routers? (Auth vs Patha) | ||
- Consider removing expanded routes, and accepting routes as a vec? (complexity/performance issues) - would need to revamp gitlab logic too | ||
- Improve our errors. | ||
- Documentation refresh. | ||
- Look into query/headers/... |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,3 @@ | ||
# Authority Router | ||
|
||
TODO |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,3 @@ | ||
# Method Router | ||
|
||
TODO |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,3 @@ | ||
# Path Router | ||
|
||
TODO |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,104 @@ | ||
#![allow(dead_code)] | ||
#![allow(clippy::needless_pass_by_ref_mut)] | ||
|
||
use errors::{ | ||
AuthorityConstraintError, AuthorityDeleteError, AuthorityInsertError, AuthoritySearchError, | ||
}; | ||
use id::AuthorityIdGenerator; | ||
use node::Node; | ||
use smallvec::SmallVec; | ||
use state::RootState; | ||
use std::{collections::HashMap, fmt::Display}; | ||
|
||
pub mod constraints; | ||
// pub mod delete; | ||
pub mod display; | ||
pub mod errors; | ||
// pub mod find; | ||
pub mod id; | ||
// pub mod insert; | ||
pub mod node; | ||
// pub mod optimize; | ||
pub mod parser; | ||
// pub mod search; | ||
pub mod state; | ||
|
||
pub use constraints::AuthorityConstraint; | ||
pub use id::AuthorityId; | ||
|
||
#[derive(Clone, Debug, Eq, PartialEq)] | ||
pub struct AuthorityData<'r> { | ||
pub id: AuthorityId, | ||
pub authority: &'r str, | ||
} | ||
|
||
#[derive(Debug, Eq, PartialEq)] | ||
pub struct AuthorityMatch<'r, 'p> { | ||
pub id: AuthorityId, | ||
pub authority: &'r str, | ||
pub parameters: AuthorityParameters<'r, 'p>, | ||
} | ||
|
||
pub type AuthorityParameters<'r, 'p> = SmallVec<[(&'r str, &'p str); 4]>; | ||
|
||
#[derive(Clone)] | ||
pub struct StoredConstraint { | ||
pub type_name: &'static str, | ||
pub check: fn(&str) -> bool, | ||
} | ||
|
||
#[derive(Clone)] | ||
pub struct Authorityauthorityr<'r> { | ||
pub root: Node<'r, RootState>, | ||
pub constraints: HashMap<&'r str, StoredConstraint>, | ||
pub id: AuthorityIdGenerator, | ||
} | ||
|
||
impl<'r> Authorityauthorityr<'r> { | ||
#[must_use] | ||
pub fn new() -> Self { | ||
todo!() | ||
} | ||
|
||
pub fn constraint<C: AuthorityConstraint>(&mut self) -> Result<(), AuthorityConstraintError> { | ||
todo!() | ||
} | ||
|
||
pub(crate) fn conflicts( | ||
&self, | ||
_authority: &str, | ||
) -> Result<Option<AuthorityId>, AuthorityDeleteError> { | ||
todo!() | ||
} | ||
|
||
pub(crate) fn insert( | ||
&mut self, | ||
_authority: &'r str, | ||
) -> Result<AuthorityId, AuthorityInsertError> { | ||
todo!() | ||
} | ||
|
||
pub(crate) fn find( | ||
&self, | ||
_authority: &str, | ||
) -> Result<Option<AuthorityId>, AuthorityDeleteError> { | ||
todo!() | ||
} | ||
|
||
pub(crate) fn delete(&mut self, _authority: &str) { | ||
todo!() | ||
} | ||
|
||
pub(crate) fn search<'p>( | ||
&'r self, | ||
_path: &'p [u8], | ||
) -> Result<Option<AuthorityMatch<'r, 'p>>, AuthoritySearchError> { | ||
todo!() | ||
} | ||
} | ||
|
||
impl Display for Authorityauthorityr<'_> { | ||
fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result { | ||
write!(f, "{}", self.root) | ||
} | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,5 @@ | ||
pub trait AuthorityConstraint: Send + Sync { | ||
const NAME: &'static str; | ||
|
||
fn check(segment: &str) -> bool; | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,103 @@ | ||
use crate::router::authority::{node::Node, state::State}; | ||
use std::fmt::{Display, Write}; | ||
|
||
impl<S: State> Display for Node<'_, S> { | ||
fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result { | ||
fn debug_node<S: State>( | ||
output: &mut String, | ||
node: &Node<'_, S>, | ||
padding: &str, | ||
is_top: bool, | ||
is_last: bool, | ||
) -> std::fmt::Result { | ||
let key = node.state.key(); | ||
|
||
if is_top { | ||
if let Some(data) = node.data.as_ref() { | ||
writeln!(output, "{key} [{}]", data.id)?; | ||
} else { | ||
writeln!(output, "{key}")?; | ||
} | ||
} else { | ||
let branch = if is_last { "╰─" } else { "├─" }; | ||
if let Some(data) = node.data.as_ref() { | ||
writeln!(output, "{padding}{branch} {key} [{}]", data.id)?; | ||
} else { | ||
writeln!(output, "{padding}{branch} {key}")?; | ||
} | ||
} | ||
|
||
let new_prefix = if is_top { | ||
padding.to_owned() | ||
} else if is_last { | ||
format!("{padding} ") | ||
} else { | ||
format!("{padding}│ ") | ||
}; | ||
|
||
let mut total_children = node.static_children.len() | ||
+ node.dynamic_children.len() | ||
+ node.wildcard_children.len() | ||
+ node.end_wildcard_children.len(); | ||
|
||
for child in node.static_children.iter() { | ||
total_children -= 1; | ||
debug_node(output, child, &new_prefix, false, total_children == 0)?; | ||
} | ||
|
||
for child in node.dynamic_children.iter() { | ||
total_children -= 1; | ||
debug_node(output, child, &new_prefix, false, total_children == 0)?; | ||
} | ||
|
||
for child in node.wildcard_children.iter() { | ||
total_children -= 1; | ||
debug_node(output, child, &new_prefix, false, total_children == 0)?; | ||
} | ||
|
||
for child in node.end_wildcard_children.iter() { | ||
total_children -= 1; | ||
debug_node(output, child, &new_prefix, false, total_children == 0)?; | ||
} | ||
|
||
Ok(()) | ||
} | ||
|
||
let mut output = String::new(); | ||
let padding = " ".repeat(self.state.padding()); | ||
|
||
// Handle root node manually | ||
if self.state.key().is_empty() { | ||
let total_children = self.static_children.len() | ||
+ self.dynamic_children.len() | ||
+ self.wildcard_children.len() | ||
+ self.end_wildcard_children.len(); | ||
|
||
let mut remaining = total_children; | ||
|
||
for child in self.static_children.iter() { | ||
remaining -= 1; | ||
debug_node(&mut output, child, "", true, remaining == 0)?; | ||
} | ||
|
||
for child in self.dynamic_children.iter() { | ||
remaining -= 1; | ||
debug_node(&mut output, child, "", true, remaining == 0)?; | ||
} | ||
|
||
for child in self.wildcard_children.iter() { | ||
remaining -= 1; | ||
debug_node(&mut output, child, "", true, remaining == 0)?; | ||
} | ||
|
||
for child in self.end_wildcard_children.iter() { | ||
remaining -= 1; | ||
debug_node(&mut output, child, "", true, remaining == 0)?; | ||
} | ||
} else { | ||
debug_node(&mut output, self, &padding, true, true)?; | ||
} | ||
|
||
write!(f, "{}", output.trim_end()) | ||
} | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,14 @@ | ||
pub mod constraint; | ||
pub use constraint::AuthorityConstraintError; | ||
|
||
pub mod delete; | ||
pub use delete::AuthorityDeleteError; | ||
|
||
pub mod insert; | ||
pub use insert::AuthorityInsertError; | ||
|
||
pub mod search; | ||
pub use search::AuthoritySearchError; | ||
|
||
pub mod template; | ||
pub use template::AuthorityTemplateError; |
Oops, something went wrong.