webgraph_cli/bench/
bf_visit.rs1use crate::GlobalArgs;
10use anyhow::Result;
11use clap::Parser;
12use dsi_bitstream::prelude::*;
13use dsi_progress_logger::prelude::*;
14use std::collections::VecDeque;
15use std::path::PathBuf;
16use sux::prelude::BitVec;
17use sux::traits::BitVecOpsMut;
18use webgraph::prelude::*;
19
20#[derive(Parser, Debug)]
21#[command(name = "bf-visit", about = "Benchmarks a breadth-first visit.", long_about = None)]
22pub struct CliArgs {
23 pub src: PathBuf,
25 #[arg(short = 'S', long = "static")]
27 pub _static: bool,
28 #[arg(short = 'R', long, default_value_t = 1)]
30 pub repeats: usize,
31
32 #[clap(long, default_value = "false")]
33 pub mmap: bool,
35}
36
37pub fn main(_global_args: GlobalArgs, args: CliArgs) -> Result<()> {
38 let config = BvGraph::with_basename(&args.src);
39
40 for _ in 0..args.repeats {
41 match (get_endianness(&args.src)?.as_str(), args.mmap) {
42 #[cfg(feature = "be_bins")]
43 (BE::NAME, true) => match args._static {
44 true => visit(
45 config
46 .clone()
47 .mode::<Mmap>()
48 .flags(MemoryFlags::TRANSPARENT_HUGE_PAGES | MemoryFlags::RANDOM_ACCESS)
49 .endianness::<BE>()
50 .dispatch::<Static>()
51 .load()?,
52 )?,
53 false => visit(config.clone().endianness::<BE>().load()?)?,
54 },
55 #[cfg(feature = "be_bins")]
56 (BE::NAME, false) => match args._static {
57 true => visit(
58 config
59 .clone()
60 .mode::<LoadMmap>()
61 .flags(MemoryFlags::TRANSPARENT_HUGE_PAGES | MemoryFlags::RANDOM_ACCESS)
62 .endianness::<BE>()
63 .dispatch::<Static>()
64 .load()?,
65 )?,
66 false => visit(config.clone().endianness::<BE>().load()?)?,
67 },
68 #[cfg(feature = "le_bins")]
69 (LE::NAME, true) => match args._static {
70 true => visit(
71 config
72 .clone()
73 .mode::<Mmap>()
74 .flags(MemoryFlags::TRANSPARENT_HUGE_PAGES | MemoryFlags::RANDOM_ACCESS)
75 .endianness::<LE>()
76 .dispatch::<Static>()
77 .load()?,
78 )?,
79 false => visit(config.clone().endianness::<LE>().load()?)?,
80 },
81 #[cfg(feature = "le_bins")]
82 (LE::NAME, false) => match args._static {
83 true => visit(
84 config
85 .clone()
86 .mode::<LoadMmap>()
87 .flags(MemoryFlags::TRANSPARENT_HUGE_PAGES | MemoryFlags::RANDOM_ACCESS)
88 .endianness::<LE>()
89 .dispatch::<Static>()
90 .load()?,
91 )?,
92 false => visit(config.clone().endianness::<LE>().load()?)?,
93 },
94 (e, _) => panic!("Unknown endianness: {}", e),
95 };
96 }
97 Ok(())
98}
99
100fn visit(graph: impl RandomAccessGraph) -> Result<()> {
101 let num_nodes = graph.num_nodes();
102 let mut seen = BitVec::new(num_nodes);
103 let mut queue = VecDeque::new();
104
105 let mut pl = ProgressLogger::default();
106 pl.display_memory(true)
107 .item_name("node")
108 .local_speed(true)
109 .expected_updates(Some(num_nodes));
110 pl.start("Visiting graph...");
111
112 for start in 0..num_nodes {
113 if seen[start] {
114 continue;
115 }
116 queue.push_back(start as _);
117 seen.set(start, true);
118
119 while !queue.is_empty() {
120 pl.light_update();
121 let current_node = queue.pop_front().unwrap();
122 for succ in graph.successors(current_node) {
123 if !seen[succ] {
124 queue.push_back(succ);
125 seen.set(succ as _, true);
126 }
127 }
128 }
129 }
130
131 pl.done();
132
133 Ok(())
134}