Skip to content

Commit

Permalink
Add _mut methods for edge mutation for faster single-thread access (#121
Browse files Browse the repository at this point in the history
)

* Add _mut methods for edge mutation for faster single-thread access

* Avoid duplication layout application
  • Loading branch information
s1ck authored Nov 17, 2023
1 parent 39b5165 commit 8bbb9c8
Show file tree
Hide file tree
Showing 2 changed files with 82 additions and 23 deletions.
84 changes: 61 additions & 23 deletions crates/builder/src/graph/adj_list.rs
Original file line number Diff line number Diff line change
Expand Up @@ -58,8 +58,28 @@ impl<NI: Idx, EV> AdjacencyList<NI, EV> {
#[inline]
pub(crate) fn insert(&self, source: NI, target: Target<NI, EV>) {
let mut edges = self.edges[source.index()].write().unwrap();
Self::apply_layout(self.layout, &mut edges, target);
}

match self.layout {
#[inline]
pub(crate) fn insert_mut(&mut self, source: NI, target: Target<NI, EV>) {
let edges = self.edges[source.index()].get_mut().unwrap();
Self::apply_layout(self.layout, edges, target);
}

#[inline]
fn check_bounds(&self, node: NI) -> Result<(), crate::Error> {
if node >= self.node_count() {
return Err(crate::Error::MissingNode {
node: format!("{}", node.index()),
});
};
Ok(())
}

#[inline]
fn apply_layout(layout: CsrLayout, edges: &mut Vec<Target<NI, EV>>, target: Target<NI, EV>) {
match layout {
CsrLayout::Sorted => match edges.binary_search(&target) {
Ok(i) => edges.insert(i, target),
Err(i) => edges.insert(i, target),
Expand Down Expand Up @@ -345,26 +365,35 @@ impl<NI: Idx, NV> EdgeMutation<NI> for DirectedALGraph<NI, NV> {
fn add_edge(&self, source: NI, target: NI) -> Result<(), crate::Error> {
self.add_edge_with_value(source, target, ())
}

fn add_edge_mut(&mut self, source: NI, target: NI) -> Result<(), crate::Error> {
self.add_edge_with_value_mut(source, target, ())
}
}

impl<NI: Idx, NV, EV: Copy> EdgeMutationWithValues<NI, EV> for DirectedALGraph<NI, NV, EV> {
fn add_edge_with_value(&self, source: NI, target: NI, value: EV) -> Result<(), crate::Error> {
if source >= self.al_out.node_count() {
return Err(crate::Error::MissingNode {
node: format!("{}", source.index()),
});
}
if target >= self.al_inc.node_count() {
return Err(crate::Error::MissingNode {
node: format!("{}", target.index()),
});
}

self.al_out.check_bounds(source)?;
self.al_inc.check_bounds(target)?;
self.al_out.insert(source, Target::new(target, value));
self.al_inc.insert(target, Target::new(source, value));

Ok(())
}

fn add_edge_with_value_mut(
&mut self,
source: NI,
target: NI,
value: EV,
) -> Result<(), crate::Error> {
self.al_out.check_bounds(source)?;
self.al_inc.check_bounds(target)?;
self.al_out.insert_mut(source, Target::new(target, value));
self.al_inc.insert_mut(target, Target::new(source, value));

Ok(())
}
}

impl<NI, EV, E> From<(E, CsrLayout)> for DirectedALGraph<NI, (), EV>
Expand Down Expand Up @@ -482,26 +511,35 @@ impl<NI: Idx, NV> EdgeMutation<NI> for UndirectedALGraph<NI, NV, ()> {
fn add_edge(&self, source: NI, target: NI) -> Result<(), crate::Error> {
self.add_edge_with_value(source, target, ())
}

fn add_edge_mut(&mut self, source: NI, target: NI) -> Result<(), crate::Error> {
self.add_edge_with_value_mut(source, target, ())
}
}

impl<NI: Idx, NV, EV: Copy> EdgeMutationWithValues<NI, EV> for UndirectedALGraph<NI, NV, EV> {
fn add_edge_with_value(&self, source: NI, target: NI, value: EV) -> Result<(), crate::Error> {
if source >= self.al.node_count() {
return Err(crate::Error::MissingNode {
node: format!("{}", source.index()),
});
}
if target >= self.al.node_count() {
return Err(crate::Error::MissingNode {
node: format!("{}", target.index()),
});
}

self.al.check_bounds(source)?;
self.al.check_bounds(target)?;
self.al.insert(source, Target::new(target, value));
self.al.insert(target, Target::new(source, value));

Ok(())
}

fn add_edge_with_value_mut(
&mut self,
source: NI,
target: NI,
value: EV,
) -> Result<(), crate::Error> {
self.al.check_bounds(source)?;
self.al.check_bounds(target)?;
self.al.insert_mut(source, Target::new(target, value));
self.al.insert_mut(target, Target::new(source, value));

Ok(())
}
}

impl<NI, EV, E> From<(E, CsrLayout)> for UndirectedALGraph<NI, (), EV>
Expand Down
21 changes: 21 additions & 0 deletions crates/builder/src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -420,6 +420,16 @@ pub trait EdgeMutation<NI: Idx> {
/// If either the source or the target node does not exist,
/// the method will return [`Error::MissingNode`].
fn add_edge(&self, source: NI, target: NI) -> Result<(), Error>;

/// Adds a new edge between the given source and target node.
///
/// Does not require locking the node-local list due to `&mut self`.
///
/// # Errors
///
/// If either the source or the target node does not exist,
/// the method will return [`Error::MissingNode`].
fn add_edge_mut(&mut self, source: NI, target: NI) -> Result<(), Error>;
}

/// Allows adding new edges to a graph.
Expand All @@ -432,6 +442,17 @@ pub trait EdgeMutationWithValues<NI: Idx, EV> {
/// If either the source or the target node does not exist,
/// the method will return [`Error::MissingNode`].
fn add_edge_with_value(&self, source: NI, target: NI, value: EV) -> Result<(), Error>;

/// Adds a new edge between the given source and target node
/// and assigns the given value to it.
///
/// Does not require locking the node-local list due to `&mut self`.
///
/// # Errors
///
/// If either the source or the target node does not exist,
/// the method will return [`Error::MissingNode`].
fn add_edge_with_value_mut(&mut self, source: NI, target: NI, value: EV) -> Result<(), Error>;
}

#[repr(transparent)]
Expand Down

0 comments on commit 8bbb9c8

Please sign in to comment.