use std::collections::BTreeMap;
use criterion::Bencher;
use safegraph::graph::capability::InsertNode;
use safegraph::graph::{Graph, GraphOperation, GraphProperty};
use safegraph::raw_graph::flat_adj_edge::{FlatAdjEdgeGraph, NodeRepr as FlatNodeRepr, TNone};
use safegraph::raw_graph::linked_adj_edge::{EdgeRepr, LinkedAdjEdgeGraph, NodeRepr as LinkedNodeRepr};
use crate::common::{edge_is_victim, node_is_victim, Workload};
macro_rules! scoped_adapter {
($name:ident, $G:ty) => {
pub mod $name {
use super::*;
pub type G = $G;
pub fn build(w: &Workload) -> G {
let mut g = G::default();
g.scope_mut(|mut ctx| {
let ixs: Vec<_> = (0..w.n)
.map(|i| ctx.insert_node(i).expect("insert_node"))
.collect();
for (j, &(f, t)) in w.edges.iter().enumerate() {
ctx.insert_edge(j, [ixs[f as usize], ixs[t as usize]])
.expect("insert_edge");
}
});
g
}
pub fn traverse_sum(g: &G) -> usize {
g.scope(|ctx| {
let mut total = 0usize;
for nix in Graph::node_indices(ctx) {
total = total.wrapping_add(*ctx.node(nix));
for (_, e, _) in ctx.walks_from(nix).map(|w| w.get()) {
total = total.wrapping_add(*e);
}
}
total
})
}
pub fn out_degree_sum(g: &G) -> usize {
g.scope(|ctx| {
let mut total = 0usize;
for nix in Graph::node_indices(ctx) {
total += ctx.walks_from(nix).count();
}
total
})
}
pub fn bench_random_access(g: &G, order: &[usize], b: &mut Bencher) {
g.scope(|ctx| {
let all: Vec<_> = Graph::node_indices(ctx).collect();
let ixs: Vec<_> = order.iter().map(|&i| all[i]).collect();
b.iter(|| {
let mut total = 0usize;
for &ix in &ixs {
total = total.wrapping_add(*ctx.node(ix));
}
std::hint::black_box(total)
});
});
}
pub fn remove_edge_set(g: &mut G) {
g.scope_mut(|ctx| {
let victims: Vec<_> = Graph::edge_indices(&*ctx)
.filter(|&e| edge_is_victim(*ctx.edge(e)))
.collect();
ctx.remove_nodes_edges(None, victims);
});
}
pub fn remove_node_set(g: &mut G) {
g.scope_mut(|ctx| {
let victims: Vec<_> = Graph::node_indices(&*ctx)
.filter(|&n| node_is_victim(*ctx.node(n)))
.collect();
ctx.remove_nodes_edges(victims, None);
});
}
pub fn counts(g: &G) -> (usize, usize) {
g.scope(|ctx| (ctx.nodes().count(), ctx.edges().count()))
}
}
};
}
scoped_adapter!(sg_vec_scoped, safegraph::VecGraph<usize, usize>);
scoped_adapter!(
sg_flat,
FlatAdjEdgeGraph<Vec<(usize, FlatNodeRepr<Vec<(usize, u32)>, TNone>)>>
);
scoped_adapter!(
sg_btree,
LinkedAdjEdgeGraph<
BTreeMap<usize, LinkedNodeRepr<Option<usize>>>,
BTreeMap<usize, EdgeRepr<usize, Option<usize>>>,
>
);
pub mod sg_vec_stabilized {
use super::*;
use safegraph::graph::stabilized::{EdgeIx as StabEdgeIx, NodeIx as StabNodeIx, Stabilized};
pub type G = Stabilized<
LinkedAdjEdgeGraph<
Vec<(StabNodeIx<usize>, LinkedNodeRepr<u32>)>,
Vec<(StabEdgeIx<usize>, EdgeRepr<u32, u32>)>,
>,
usize,
usize,
>;
pub type NodeIx = <G as GraphProperty>::NodeIx;
pub fn build(w: &Workload) -> G {
let mut g: G = safegraph::VecGraph::<usize, usize>::default().stabilize();
let ixs: Vec<NodeIx> = (0..w.n)
.map(|i| g.insert_node(i).expect("insert_node"))
.collect();
for (j, &(f, t)) in w.edges.iter().enumerate() {
g.insert_edge(j, [ixs[f as usize], ixs[t as usize]])
.expect("insert_edge");
}
g
}
pub fn traverse_sum(g: &G) -> usize {
let mut total = 0usize;
for nix in Graph::node_indices(g) {
total = total.wrapping_add(*g.node(nix));
for (_, e, _) in g.walks_from(nix).map(|w| w.get()) {
total = total.wrapping_add(*e);
}
}
total
}
pub fn out_degree_sum(g: &G) -> usize {
Graph::node_indices(g).map(|nix| g.walks_from(nix).count()).sum()
}
pub fn access_indices(g: &G, order: &[usize]) -> Vec<NodeIx> {
let all: Vec<NodeIx> = Graph::node_indices(g).collect();
order.iter().map(|&i| all[i]).collect()
}
pub fn access_sum(g: &G, ixs: &[NodeIx]) -> usize {
let mut total = 0usize;
for &ix in ixs {
total = total.wrapping_add(*g.node(ix));
}
total
}
pub fn remove_edge_set(g: &mut G) {
let victims: Vec<_> = Graph::edge_indices(g)
.filter(|&e| edge_is_victim(*g.edge(e)))
.collect();
g.remove_nodes_edges(None, victims);
}
pub fn remove_node_set(g: &mut G) {
let victims: Vec<_> = Graph::node_indices(g)
.filter(|&nix| node_is_victim(*g.node(nix)))
.collect();
g.remove_nodes_edges(victims, None);
}
pub fn counts(g: &G) -> (usize, usize) {
(Graph::node_indices(g).count(), Graph::edge_indices(g).count())
}
}
pub mod sg_vec_checked {
use super::*;
pub type G = safegraph::VecGraph<usize, usize>;
pub type NodeIx = <G as GraphProperty>::NodeIx;
type EdgeIx = <G as GraphProperty>::EdgeIx;
pub fn build(w: &Workload) -> G {
let mut g = G::default();
let ixs: Vec<NodeIx> = (0..w.n)
.map(|i| unsafe { InsertNode::insert_node_unchecked(&mut g, i) }.expect("insert_node"))
.collect();
for (j, &(f, t)) in w.edges.iter().enumerate() {
let endpoints = [ixs[f as usize], ixs[t as usize]];
assert!(endpoints
.iter()
.all(|&n| GraphOperation::contains_node_index(&g, n)));
unsafe { Graph::insert_edge_unchecked(&mut g, j, endpoints) }.expect("insert_edge");
}
g
}
pub fn traverse_sum(g: &G) -> usize {
let mut total = 0usize;
for nix in GraphOperation::node_indices(g) {
total = total.wrapping_add(*g.node(nix));
for (_, e, _) in unsafe { GraphOperation::walks_from_unchecked(g, nix) }.map(|w| w.get()) {
total = total.wrapping_add(*e);
}
}
total
}
pub fn out_degree_sum(g: &G) -> usize {
let mut total = 0usize;
for nix in GraphOperation::node_indices(g) {
total += unsafe { GraphOperation::walks_from_unchecked(g, nix) }.count();
}
total
}
pub fn access_indices(g: &G, order: &[usize]) -> Vec<NodeIx> {
let all: Vec<NodeIx> = GraphOperation::node_indices(g).collect();
order.iter().map(|&i| all[i]).collect()
}
pub fn access_sum(g: &G, ixs: &[NodeIx]) -> usize {
let mut total = 0usize;
for &ix in ixs {
total = total.wrapping_add(*g.node(ix));
}
total
}
pub fn remove_edge_set(g: &mut G) {
let victims: Vec<EdgeIx> = GraphOperation::edge_indices(&*g)
.filter(|&e| edge_is_victim(*g.edge(e)))
.collect();
g.remove_nodes_edges(None, victims);
}
pub fn remove_node_set(g: &mut G) {
let victims: Vec<NodeIx> = GraphOperation::node_indices(&*g)
.filter(|&n| node_is_victim(*g.node(n)))
.collect();
g.remove_nodes_edges(victims, None);
}
pub fn counts(g: &G) -> (usize, usize) {
(GraphOperation::len_node(g), GraphOperation::len_edge(g))
}
}
pub mod pg {
use petgraph::graph::{DiGraph, NodeIndex};
use crate::common::{edge_is_victim, node_is_victim, Workload};
pub type G = DiGraph<usize, usize>;
pub type NodeIx = NodeIndex;
pub fn build(w: &Workload) -> G {
let mut g = DiGraph::new();
let ixs: Vec<NodeIndex> = (0..w.n).map(|i| g.add_node(i)).collect();
for (j, &(f, t)) in w.edges.iter().enumerate() {
g.add_edge(ixs[f as usize], ixs[t as usize], j);
}
g
}
pub fn traverse_sum(g: &G) -> usize {
let mut total = 0usize;
for n in g.node_indices() {
total = total.wrapping_add(*g.node_weight(n).unwrap());
for er in g.edges(n) {
total = total.wrapping_add(*er.weight());
}
}
total
}
pub fn out_degree_sum(g: &G) -> usize {
g.node_indices().map(|n| g.edges(n).count()).sum()
}
pub fn access_indices(g: &G, order: &[usize]) -> Vec<NodeIx> {
let _ = g;
order.iter().map(|&i| NodeIndex::new(i)).collect()
}
pub fn access_sum(g: &G, ixs: &[NodeIx]) -> usize {
let mut total = 0usize;
for &ix in ixs {
total = total.wrapping_add(*g.node_weight(ix).unwrap());
}
total
}
pub fn remove_edge_set(g: &mut G) {
g.retain_edges(|gg, e| !edge_is_victim(gg[e]));
}
pub fn remove_node_set(g: &mut G) {
g.retain_nodes(|gg, n| !node_is_victim(gg[n]));
}
pub fn counts(g: &G) -> (usize, usize) {
(g.node_count(), g.edge_count())
}
}
pub mod pg_stable {
use petgraph::stable_graph::{EdgeIndex, NodeIndex, StableDiGraph};
use crate::common::{edge_is_victim, node_is_victim, Workload};
pub type G = StableDiGraph<usize, usize>;
pub type NodeIx = NodeIndex;
pub fn build(w: &Workload) -> G {
let mut g = StableDiGraph::new();
let ixs: Vec<NodeIndex> = (0..w.n).map(|i| g.add_node(i)).collect();
for (j, &(f, t)) in w.edges.iter().enumerate() {
g.add_edge(ixs[f as usize], ixs[t as usize], j);
}
g
}
pub fn traverse_sum(g: &G) -> usize {
let mut total = 0usize;
for n in g.node_indices() {
total = total.wrapping_add(*g.node_weight(n).unwrap());
for er in g.edges(n) {
total = total.wrapping_add(*er.weight());
}
}
total
}
pub fn out_degree_sum(g: &G) -> usize {
g.node_indices().map(|n| g.edges(n).count()).sum()
}
pub fn access_indices(g: &G, order: &[usize]) -> Vec<NodeIx> {
let all: Vec<NodeIndex> = g.node_indices().collect();
order.iter().map(|&i| all[i]).collect()
}
pub fn access_sum(g: &G, ixs: &[NodeIx]) -> usize {
let mut total = 0usize;
for &ix in ixs {
total = total.wrapping_add(*g.node_weight(ix).unwrap());
}
total
}
pub fn remove_edge_set(g: &mut G) {
g.retain_edges(|gg, e| !edge_is_victim(gg[e]));
}
pub fn remove_node_set(g: &mut G) {
g.retain_nodes(|gg, n| !node_is_victim(gg[n]));
}
pub fn remove_edge_loop(g: &mut G) {
let victims: Vec<EdgeIndex> =
g.edge_indices().filter(|&e| edge_is_victim(g[e])).collect();
for e in victims {
g.remove_edge(e);
}
}
pub fn remove_node_loop(g: &mut G) {
let victims: Vec<NodeIndex> =
g.node_indices().filter(|&n| node_is_victim(g[n])).collect();
for n in victims {
g.remove_node(n);
}
}
pub fn counts(g: &G) -> (usize, usize) {
(g.node_count(), g.edge_count())
}
}